
#ifndef __MAIN_H
#define __MAIN_H


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/*
 * DEBUG_ASSERT - povoli makro debug_assert
 * ASSERT - povoli makro assert
 * MEM_CHECK - povoli kontrolu pridelovani a uvolnovani pameti
 */

#define DEBUG_ASSERT
#define ASSERT
#define MEM_CHECK

/*
 * c_idx_not_exist - konstanta oznacujici nexistujici index
 * c_array_add - konstanta o kterou se navysuje pamet(nasobena velikosti typu) pridelena dynamickym polim
 */

const unsigned c_idx_not_exist = 0xffffffff;
const unsigned c_array_add = 64;

/*
 * makro debug_assert slouzi pro debugovani v casto spoustenych usecich kodu ve finalni verzi nebude aktivni
 */
#ifdef DEBUG_ASSERT
#define debug_assert(COND)\
{\
   if (!(COND)) {\
      fprintf(stderr,"DEBUG_ASSERT: %s, line: %d\n",__FILE__,__LINE__);\
      throw;\
   }\
}
#else
#define debug_assert(COND)
#endif

/*
 * makro assert vetsina bude nahrazena chybovou zpravou, pri nesplneni podminky makro vypise 
 * ve kterem souboru a na kterem radku se nachazi, neukoncuje program
 */
#ifdef ASSERT
#define assert(COND)\
{\
   if (!(COND)) {\
      fprintf(stderr,"ASSERT: %s, line: %d\n",__FILE__,__LINE__);\
      throw;\
   }\
}
#else
#define assert(COND)
#endif

/*
 * struktura implementujici kontrolu pameti, na zacatku programu musi byt zavolana funkce mc_init() a
 * na konci mc_clear(), pro alokaci a dealokaci pameti se pouzivaji funkce cmalloc a cfree
 */
#ifdef MEM_CHECK

/* --- definice struktury mce_struct_s ---
 * novy zpusob zpravy pameti pomoci hashovaneho pole
 * udrzuje zaznam o pozici pridelene pameti a jeji velikosti
 * muze byt vypnuta, ale dopad na vykon je minimalni
 */

/*
 * zaznam popisujici blok pameti
 */
struct mce_block_s
{
   void *location;
   unsigned size;
   unsigned next_idx;
};

/*
 * struktura, ktera uchovava seznam zaznamu o pridelene pameti
 */
struct mce_struct_s
{
   unsigned size;
   unsigned data_start;
   unsigned empty_start;
   mce_block_s *data;

   inline void init();
   inline void clear();
   void check();
   void copy_resize(unsigned a_size);
   void *create_block(unsigned a_size);
   void delete_block(void *a_location);
   void print_hash(bool set);
};

/*
 * inicializace kontrolni struktury
 */
inline void mce_struct_s::init()
{
   size = 0;
   data_start = c_idx_not_exist;
   empty_start = c_idx_not_exist;
   data = NULL;
}

/*
 * uvolneni kontrolni struktury z pameti,
 * pred uvolnenim provede kontrolu zda byly vsechny bloky uvolneny
 */
inline void mce_struct_s::clear()
{
   check();

   if (data != NULL) {
      free(data);
   }

   init();
}

/*
 * kontrola zda jsou vsechny bloky pameti uvolneny, pokud ne 
 * zobraz na chybovy vystup informace o neuvolnenych blocich
 */
void mce_struct_s::check()
{
   if (data_start == c_idx_not_exist) {
      return;
   }

   unsigned idx = data_start;
   do {
      mce_block_s &block = data[idx];

      fprintf(stderr,"MEM_CHECK_ENCHANCED: leak at: %d, size: %d\n",(unsigned)block.location,block.size);
      free(block.location);

      idx = block.next_idx;
   } while(idx != c_idx_not_exist);
}

/*
 * zmena velikosti pole pro ukladani zaznamu o pridelene pameti
 */
void mce_struct_s::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= size);

   if (a_size == size) {
      return;
   }

   mce_block_s *n_data = (mce_block_s *)malloc(a_size*sizeof(mce_block_s));

   if (size != 0) {
      memcpy(n_data,data,size*sizeof(mce_block_s));
      free(data);
   }

   unsigned idx = size;
   unsigned idx_end = a_size - 1;

   if (idx < idx_end) {
      do {
	 n_data[idx].next_idx = idx + 1;
      } while(++idx < idx_end);
   }

   n_data[idx].next_idx = empty_start;
   empty_start = size;

   data = n_data;
   size = a_size;
}

/*
 * alokuje novy blok pameti, ulozi jej do struktury a
 * vrati ukazatel na tento blok
 */
void *mce_struct_s::create_block(unsigned a_size)
{
   void *location = malloc(a_size);

   if (empty_start == c_idx_not_exist) {
      copy_resize(size + c_array_add);
   }

   unsigned old_empty_start = empty_start;
   mce_block_s &block = data[old_empty_start];

   empty_start = block.next_idx;
   block.next_idx = data_start;
   data_start = old_empty_start;

   block.location = location;
   block.size = a_size;

   return location;
}

/*
 * uvolni alokovany blok z pameti a zaroven zkontroluje jestli
 * byl vubec alokovan
 */
void mce_struct_s::delete_block(void *a_location)
{
   debug_assert(data_start != c_idx_not_exist);

   unsigned idx = data_start;
   unsigned old_idx = c_idx_not_exist;
   do {
      mce_block_s &block = data[idx];

      if (block.location == a_location) {
	 break;
      }

      old_idx = idx;
      idx = block.next_idx;

   } while(idx != c_idx_not_exist);

   debug_assert(idx != c_idx_not_exist);

   mce_block_s &block = data[idx];

   if (old_idx == c_idx_not_exist) {
      data_start = block.next_idx;
   }
   else {
      data[old_idx].next_idx = block.next_idx;
   }

   block.next_idx = empty_start;
   empty_start = idx;

   free(block.location);
}

#define mc_init() mce.init();
#define mc_clear() mce.clear();

#define cmalloc(SIZE) mce.create_block(SIZE)
#define cfree(LOCATION) mce.delete_block(LOCATION)

mce_struct_s mce;

#else

#define mc_init()
#define mc_clear()

#define cmalloc(SIZE) malloc(SIZE)
#define cfree(LOCATION) free(LOCATION)

#endif


// - datovy typ instrukce v semantickem bytovem kodu -

typedef unsigned short t_si_type;

// --- struct string_s definition ---

/*
 * struktura implementujici retezec, zapsana takovym zpusobem,
 * aby se mohla pouzit v definicich objektu skriptu process.pl
 */
struct string_s
{
   unsigned size;
   char *data;

   inline void init();
   inline void clear();
   inline void create(unsigned a_length);
   inline void set(unsigned a_length,char *a_data);
   void set_format(unsigned a_length,char *a_data);
   void set_format_parm(unsigned a_length,char *a_data,unsigned a_parm_cnt,unsigned *params);
   inline void conc_set(unsigned a_flength,char *a_fdata,unsigned a_slength,char *a_sdata);
   inline void flush_all();
   inline void swap(string_s &second);
   inline char &operator[](unsigned a_idx);
   inline string_s &operator=(string_s &src);
   inline bool operator==(string_s &second);
   inline bool compare_char_ptr(unsigned a_length,char *a_data);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
   inline bool load_text_file(char *file);
   inline bool save_text_file(char *file);
};

inline void string_s::init()
{
   size = 0;
   data = NULL;
}

inline void string_s::clear()
{
   if (data != NULL) {
      cfree(data);
   }

   init();
}

inline void string_s::create(unsigned a_length)
{
   clear();
   data = (char *)cmalloc((a_length + 1)*sizeof(char));

   data[a_length] = '\0';
   size = a_length + 1;
}

inline void string_s::set(unsigned a_length,char *a_data)
{
   clear();
   data = (char *)cmalloc((a_length + 1)*sizeof(char));

   if (a_length != 0) {
      memcpy(data,a_data,a_length*sizeof(char));
   }

   data[a_length] = '\0';
   size = a_length + 1;
}

inline void string_s::conc_set(unsigned a_flength,char *a_fdata,unsigned a_slength,char *a_sdata)
{
   clear();
   data = (char *)cmalloc((a_flength + a_slength + 1)*sizeof(char));

   if (a_flength != 0) {
      memcpy(data,a_fdata,a_flength*sizeof(char));
   }

   if (a_slength != 0) {
      memcpy(data + a_flength,a_sdata,a_slength*sizeof(char));
   }

   data[a_flength + a_slength] = '\0';
   size = a_flength + a_slength + 1;
}

inline void string_s::flush_all()
{
}

inline void string_s::swap(string_s &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   char *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline char &string_s::operator[](unsigned a_idx)
{
   debug_assert(a_idx < size);
   return data[a_idx];
}

inline string_s &string_s::operator=(string_s &src)
{
   clear();
   if (src.size == 0) return *this;
   data = (char *)cmalloc(src.size*sizeof(char));
   memcpy(data,src.data,src.size*sizeof(char));
   size = src.size;

   return *this;
}

inline bool string_s::operator==(string_s &second)
{
   if (size != second.size) return false;
   if (size == 0) return true;
   return (memcmp(data,second.data,size*sizeof(char)) == 0);
}

inline bool string_s::compare_char_ptr(unsigned a_length,char *a_data)
{
   if (size != a_length + 1) return false;
   if (a_length == 0) return true;
   return (memcmp(data,a_data,a_length*sizeof(char)) == 0);
}

inline unsigned string_s::save_size()
{
   return sizeof(unsigned) + size*sizeof(char);
}

inline void string_s::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = size; *b_ptr += sizeof(unsigned);

   if (size == 0) return;
   memcpy(*b_ptr,data,size*sizeof(char));
   *b_ptr += size*sizeof(char);
}

inline void string_s::load_from(char **b_ptr)
{
   clear();
   size = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);

   unsigned data_size = size*sizeof(char);
   data = (char *)cmalloc(data_size);
   memcpy(data,*b_ptr,data_size);
   *b_ptr += data_size;
}

inline void string_s::print()
{
   if (size == 0) return;
   printf("%s",data);
}

inline bool string_s::load_text_file(char *file)
{
   if (file == NULL) return false;
   FILE *f = fopen(file,"rb");
   if (f == NULL) return false;

   fseek(f,0,SEEK_END);
   unsigned file_size = ftell(f);
   fseek(f,0,SEEK_SET);

   clear();
   data = (char *)cmalloc((file_size + 1)*sizeof(char));
   fread(data,file_size,1,f);
   fclose(f);

   data[file_size] = '\0';
   size = file_size + 1;

   return true;
}

inline bool string_s::save_text_file(char *file)
{
   if (file == NULL) return false;
   FILE *f = fopen(file,"wb");
   if (f == NULL) return false;

   if (size > 1) {
      fwrite(data,size - 1,1,f);
   }

   fclose(f);
   return true;
}


/*
 * ui_array_s
 */

// --- struct ui_a definition ---

typedef struct ui_a ui_array_s;

struct ui_a
{
   unsigned size;
   unsigned used;
   unsigned *data;

   inline void init();
   inline void init_size(unsigned a_size);
   inline void clear();
   inline void set(unsigned a_used,unsigned *a_data);
   inline void flush();
   inline void flush_all();
   inline void swap(ui_a &second);
   inline unsigned &operator[](unsigned a_idx);
   inline unsigned &__at(unsigned a_idx);
   inline unsigned &__tail(unsigned a_idx);
   inline unsigned &__last();
   inline unsigned &__pop();
   inline void push(unsigned a_value);
   inline void push_blank();
   inline void push_clear();
   inline unsigned &pop();
   inline unsigned &last();
   void copy_resize(unsigned a_size);
   void fill(unsigned a_value);
   unsigned get_idx(unsigned a_value);
   inline ui_a &operator=(ui_a &src);
   inline bool operator==(ui_a &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   void print();
};

// --- struct ui_a method definition ---

inline void ui_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void ui_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

inline void ui_a::clear()
{
   if (data != NULL) {
      cfree(data);
   }

   init();
}

inline void ui_a::set(unsigned a_used,unsigned *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   memcpy(data,a_data,a_used*sizeof(unsigned));
   used = a_used;
}

inline void ui_a::flush()
{
   copy_resize(used);
}

inline void ui_a::flush_all()
{
   copy_resize(used);
}

inline void ui_a::swap(ui_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   unsigned *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline unsigned &ui_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline unsigned &ui_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline unsigned &ui_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline unsigned &ui_a::__last()
{
   return data[used - 1];
}

inline unsigned &ui_a::__pop()
{
   return data[--used];
}

inline void ui_a::push(unsigned a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void ui_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void ui_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline unsigned &ui_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline unsigned &ui_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void ui_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   unsigned *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (unsigned *)cmalloc(a_size*sizeof(unsigned));
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(unsigned));
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void ui_a::fill(unsigned a_value)
{
   if (size == 0) return;

   unsigned *ptr = data;
   unsigned *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned ui_a::get_idx(unsigned a_value)
{
   if (used == 0) return c_idx_not_exist;

   unsigned *ptr = data;
   unsigned *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

inline ui_a &ui_a::operator=(ui_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);
   memcpy(data,src.data,src.used*sizeof(unsigned));

   used = src.used;
   return *this;
}

inline bool ui_a::operator==(ui_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   return (memcmp(data,second.data,used*sizeof(unsigned)) == 0);
}

inline unsigned ui_a::save_size()
{
   return sizeof(unsigned) + used*sizeof(unsigned);
}

inline void ui_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   unsigned data_size = used*sizeof(unsigned);
   memcpy(*b_ptr,data,data_size);
   *b_ptr += data_size;
}

inline void ui_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   unsigned data_size = tmp_used*sizeof(unsigned);
   memcpy(data,*b_ptr,data_size);

   *b_ptr += data_size;
   used = tmp_used;
}

void ui_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   unsigned *ptr = data;
   unsigned *ptr_end = ptr + used;

   do {
      printf("%d ",*ptr);
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * string_array_s
 */

// --- struct string_s_a definition ---

typedef struct string_s_a string_array_s;

struct string_s_a
{
   unsigned size;
   unsigned used;
   string_s *data;

   inline void init();
   inline void init_size(unsigned a_size);
   void clear();
   void set(unsigned a_used,string_s *a_data);
   inline void flush();
   inline void flush_all();
   inline void swap(string_s_a &second);
   inline string_s &operator[](unsigned a_idx);
   inline string_s &__at(unsigned a_idx);
   inline string_s &__tail(unsigned a_idx);
   inline string_s &__last();
   inline string_s &__pop();
   inline void push(string_s &a_value);
   inline void push_blank();
   inline void push_clear();
   inline string_s &pop();
   inline string_s &last();
   void copy_resize(unsigned a_size);
   void fill(string_s &a_value);
   unsigned get_idx(string_s &a_value);
   string_s_a &operator=(string_s_a &src);
   bool operator==(string_s_a &second);
   unsigned save_size();
   void save_to(char **b_ptr);
   void load_from(char **b_ptr);
   void print();
};

// --- struct string_s_a method definition ---

inline void string_s_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void string_s_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

void string_s_a::clear()
{
   if (data != NULL) {
      string_s *ptr = data;
      string_s *ptr_end = ptr + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);

      cfree(data);
   }

   init();
}

void string_s_a::set(unsigned a_used,string_s *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   string_s *ptr = data;
   string_s *ptr_end = ptr + a_used;
   string_s *a_ptr = a_data;

   do {
      *ptr = *a_ptr;
   } while(++a_ptr,++ptr < ptr_end);
   used = a_used;
}

inline void string_s_a::flush()
{
   copy_resize(used);
}

inline void string_s_a::flush_all()
{
   copy_resize(used);
}

inline void string_s_a::swap(string_s_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   string_s *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline string_s &string_s_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline string_s &string_s_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline string_s &string_s_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline string_s &string_s_a::__last()
{
   return data[used - 1];
}

inline string_s &string_s_a::__pop()
{
   return data[--used];
}

inline void string_s_a::push(string_s &a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void string_s_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void string_s_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   data[used].clear();

   used++;
}

inline string_s &string_s_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline string_s &string_s_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void string_s_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   string_s *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (string_s *)cmalloc(a_size*sizeof(string_s));

      if (a_size > used) {
	 string_s *ptr = n_data + used;
	 string_s *ptr_end = n_data + a_size;

	 do {
	    ptr->init();
	 } while(++ptr < ptr_end);
      }
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(string_s));
   }

   if (size > used) {
      string_s *ptr = data + used;
      string_s *ptr_end = data + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void string_s_a::fill(string_s &a_value)
{
   if (size == 0) return;

   string_s *ptr = data;
   string_s *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned string_s_a::get_idx(string_s &a_value)
{
   if (used == 0) return c_idx_not_exist;

   string_s *ptr = data;
   string_s *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

string_s_a &string_s_a::operator=(string_s_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);

   string_s *ptr = data;
   string_s *s_ptr = src.data;
   string_s *s_ptr_end = s_ptr + src.used;

   do {
      *ptr = *s_ptr;
   } while(++ptr,++s_ptr < s_ptr_end);

   used = src.used;
   return *this;
}

bool string_s_a::operator==(string_s_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   string_s *ptr = data;
   string_s *ptr_end = ptr + used;
   string_s *s_ptr = second.data;

   do {
      if (!(*ptr == *s_ptr)) {
	 return false;
      }
   } while(++s_ptr,++ptr < ptr_end);

   return true;
}

unsigned string_s_a::save_size()
{
   if (used == 0) return sizeof(unsigned);
   
   unsigned ret_size = sizeof(unsigned);

   string_s *ptr = data;
   string_s *ptr_end = ptr + used;

   do {
      ret_size += ptr->save_size();
   } while(++ptr < ptr_end);

   return ret_size;
}

inline void string_s_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   string_s *ptr = data;
   string_s *ptr_end = ptr + used;

   do {
      ptr->save_to(b_ptr);
   } while(++ptr < ptr_end);
}

void string_s_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   string_s *ptr = data;
   string_s *ptr_end = ptr + tmp_used;

   do {
      ptr->load_from(b_ptr);
   } while(++ptr < ptr_end);

   used = tmp_used;
}

void string_s_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   string_s *ptr = data;
   string_s *ptr_end = ptr + used;

   do {
      ptr->print();
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * string_arrays_s
 */

// --- struct string_s_a_a definition ---

typedef struct string_s_a_a string_arrays_s;

struct string_s_a_a
{
   unsigned size;
   unsigned used;
   string_s_a *data;

   inline void init();
   inline void init_size(unsigned a_size);
   void clear();
   void set(unsigned a_used,string_s_a *a_data);
   inline void flush();
   void flush_all();
   inline void swap(string_s_a_a &second);
   inline string_s_a &operator[](unsigned a_idx);
   inline string_s_a &__at(unsigned a_idx);
   inline string_s_a &__tail(unsigned a_idx);
   inline string_s_a &__last();
   inline string_s_a &__pop();
   inline void push(string_s_a &a_value);
   inline void push_blank();
   inline void push_clear();
   inline string_s_a &pop();
   inline string_s_a &last();
   void copy_resize(unsigned a_size);
   void fill(string_s_a &a_value);
   unsigned get_idx(string_s_a &a_value);
   string_s_a_a &operator=(string_s_a_a &src);
   bool operator==(string_s_a_a &second);
   unsigned save_size();
   void save_to(char **b_ptr);
   void load_from(char **b_ptr);
   void print();
};

// --- struct string_s_a_a method definition ---

inline void string_s_a_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void string_s_a_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

void string_s_a_a::clear()
{
   if (data != NULL) {
      string_s_a *ptr = data;
      string_s_a *ptr_end = ptr + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);

      cfree(data);
   }

   init();
}

void string_s_a_a::set(unsigned a_used,string_s_a *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + a_used;
   string_s_a *a_ptr = a_data;

   do {
      *ptr = *a_ptr;
   } while(++a_ptr,++ptr < ptr_end);
   used = a_used;
}

inline void string_s_a_a::flush()
{
   copy_resize(used);
}

void string_s_a_a::flush_all()
{
   if (used == 0) return;

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;

   do {
      ptr->flush_all();
   } while(++ptr < ptr_end);

   copy_resize(used);
}

inline void string_s_a_a::swap(string_s_a_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   string_s_a *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline string_s_a &string_s_a_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline string_s_a &string_s_a_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline string_s_a &string_s_a_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline string_s_a &string_s_a_a::__last()
{
   return data[used - 1];
}

inline string_s_a &string_s_a_a::__pop()
{
   return data[--used];
}

inline void string_s_a_a::push(string_s_a &a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void string_s_a_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void string_s_a_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   data[used].clear();

   used++;
}

inline string_s_a &string_s_a_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline string_s_a &string_s_a_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void string_s_a_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   string_s_a *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (string_s_a *)cmalloc(a_size*sizeof(string_s_a));

      if (a_size > used) {
	 string_s_a *ptr = n_data + used;
	 string_s_a *ptr_end = n_data + a_size;

	 do {
	    ptr->init();
	 } while(++ptr < ptr_end);
      }
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(string_s_a));
   }

   if (size > used) {
      string_s_a *ptr = data + used;
      string_s_a *ptr_end = data + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void string_s_a_a::fill(string_s_a &a_value)
{
   if (size == 0) return;

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned string_s_a_a::get_idx(string_s_a &a_value)
{
   if (used == 0) return c_idx_not_exist;

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

string_s_a_a &string_s_a_a::operator=(string_s_a_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);

   string_s_a *ptr = data;
   string_s_a *s_ptr = src.data;
   string_s_a *s_ptr_end = s_ptr + src.used;

   do {
      *ptr = *s_ptr;
   } while(++ptr,++s_ptr < s_ptr_end);

   used = src.used;
   return *this;
}

bool string_s_a_a::operator==(string_s_a_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;
   string_s_a *s_ptr = second.data;

   do {
      if (!(*ptr == *s_ptr)) {
	 return false;
      }
   } while(++s_ptr,++ptr < ptr_end);

   return true;
}

unsigned string_s_a_a::save_size()
{
   if (used == 0) return sizeof(unsigned);
   
   unsigned ret_size = sizeof(unsigned);

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;

   do {
      ret_size += ptr->save_size();
   } while(++ptr < ptr_end);

   return ret_size;
}

inline void string_s_a_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;

   do {
      ptr->save_to(b_ptr);
   } while(++ptr < ptr_end);
}

void string_s_a_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + tmp_used;

   do {
      ptr->load_from(b_ptr);
   } while(++ptr < ptr_end);

   used = tmp_used;
}

void string_s_a_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   string_s_a *ptr = data;
   string_s_a *ptr_end = ptr + used;

   do {
      ptr->print();
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * data_type_s
 */

// --- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s definition ---

typedef struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s data_type_s;

struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s
{
   unsigned cont_idx;
   string_s string;
   unsigned number;
   string_s_a types;
   string_s_a vars;
   ui_a compare_idxs;

   inline void init();
   inline void clear();
   inline void set(unsigned a_cont_idx,string_s &a_string,unsigned a_number,string_s_a &a_types,string_s_a &a_vars,ui_a &a_compare_idxs);
   inline void flush_all();
   inline void swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &second);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &src);
   inline bool operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
};

// -- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s method definition ---

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::init()
{
   string.init();
   types.init();
   vars.init();
   compare_idxs.init();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::clear()
{
   string.clear();
   types.clear();
   vars.clear();
   compare_idxs.clear();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::set(unsigned a_cont_idx,string_s &a_string,unsigned a_number,string_s_a &a_types,string_s_a &a_vars,ui_a &a_compare_idxs)
{
   cont_idx = a_cont_idx;
   string = a_string;
   number = a_number;
   types = a_types;
   vars = a_vars;
   compare_idxs = a_compare_idxs;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::flush_all()
{
   types.flush_all();
   vars.flush_all();
   compare_idxs.flush_all();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &second)
{
   unsigned tmp_cont_idx = cont_idx;
   cont_idx = second.cont_idx;
   second.cont_idx = tmp_cont_idx;

   string.swap(second.string);

   unsigned tmp_number = number;
   number = second.number;
   second.number = tmp_number;

   types.swap(second.types);

   vars.swap(second.vars);

   compare_idxs.swap(second.compare_idxs);
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s::operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &src)
{
   cont_idx = src.cont_idx;
   string = src.string;
   number = src.number;
   types = src.types;
   vars = src.vars;
   compare_idxs = src.compare_idxs;

   return *this;
}

inline bool ui_string_s_ui_string_s_a_string_s_a_ui_a_s::operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &second)
{
   return (cont_idx == second.cont_idx && string == second.string && number == second.number && types == second.types && vars == second.vars && compare_idxs == second.compare_idxs);
}

inline unsigned ui_string_s_ui_string_s_a_string_s_a_ui_a_s::save_size()
{
   return (sizeof(unsigned) + string.save_size() + sizeof(unsigned) + types.save_size() + vars.save_size() + compare_idxs.save_size());
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = cont_idx; *b_ptr += sizeof(unsigned);
   string.save_to(b_ptr);
   *(unsigned *)*b_ptr = number; *b_ptr += sizeof(unsigned);
   types.save_to(b_ptr);
   vars.save_to(b_ptr);
   compare_idxs.save_to(b_ptr);
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::load_from(char **b_ptr)
{
   cont_idx = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   string.load_from(b_ptr);
   number = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   types.load_from(b_ptr);
   vars.load_from(b_ptr);
   compare_idxs.load_from(b_ptr);
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s::print()
{
   printf("%d ",*(&cont_idx));
   (&string)->print();
   printf("%d ",*(&number));
   (&types)->print();
   (&vars)->print();
   (&compare_idxs)->print();
}


/*
 * data_types_s
 */

// --- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a definition ---

typedef struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a data_types_s;

struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a
{
   unsigned size;
   unsigned used;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *data;

   inline void init();
   inline void init_size(unsigned a_size);
   void clear();
   void set(unsigned a_used,ui_string_s_ui_string_s_a_string_s_a_ui_a_s *a_data);
   inline void flush();
   void flush_all();
   inline void swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &second);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &operator[](unsigned a_idx);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &__at(unsigned a_idx);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &__tail(unsigned a_idx);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &__last();
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &__pop();
   inline void push(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value);
   inline void push_blank();
   inline void push_clear();
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &pop();
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &last();
   void copy_resize(unsigned a_size);
   void fill(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value);
   unsigned get_idx(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value);
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &src);
   bool operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &second);
   unsigned save_size();
   void save_to(char **b_ptr);
   void load_from(char **b_ptr);
   void print();
};

// --- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a method definition ---

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::clear()
{
   if (data != NULL) {
      ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
      ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);

      cfree(data);
   }

   init();
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::set(unsigned a_used,ui_string_s_ui_string_s_a_string_s_a_ui_a_s *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + a_used;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *a_ptr = a_data;

   do {
      *ptr = *a_ptr;
   } while(++a_ptr,++ptr < ptr_end);
   used = a_used;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::flush()
{
   copy_resize(used);
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::flush_all()
{
   if (used == 0) return;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;

   do {
      ptr->flush_all();
   } while(++ptr < ptr_end);

   copy_resize(used);
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::__last()
{
   return data[used - 1];
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::__pop()
{
   return data[--used];
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::push(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   data[used].clear();

   used++;
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (ui_string_s_ui_string_s_a_string_s_a_ui_a_s *)cmalloc(a_size*sizeof(ui_string_s_ui_string_s_a_string_s_a_ui_a_s));

      if (a_size > used) {
	 ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = n_data + used;
	 ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = n_data + a_size;

	 do {
	    ptr->init();
	 } while(++ptr < ptr_end);
      }
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(ui_string_s_ui_string_s_a_string_s_a_ui_a_s));
   }

   if (size > used) {
      ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data + used;
      ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = data + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::fill(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value)
{
   if (size == 0) return;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::get_idx(ui_string_s_ui_string_s_a_string_s_a_ui_a_s &a_value)
{
   if (used == 0) return c_idx_not_exist;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *s_ptr = src.data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *s_ptr_end = s_ptr + src.used;

   do {
      *ptr = *s_ptr;
   } while(++ptr,++s_ptr < s_ptr_end);

   used = src.used;
   return *this;
}

bool ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *s_ptr = second.data;

   do {
      if (!(*ptr == *s_ptr)) {
	 return false;
      }
   } while(++s_ptr,++ptr < ptr_end);

   return true;
}

unsigned ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::save_size()
{
   if (used == 0) return sizeof(unsigned);
   
   unsigned ret_size = sizeof(unsigned);

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;

   do {
      ret_size += ptr->save_size();
   } while(++ptr < ptr_end);

   return ret_size;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;

   do {
      ptr->save_to(b_ptr);
   } while(++ptr < ptr_end);
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + tmp_used;

   do {
      ptr->load_from(b_ptr);
   } while(++ptr < ptr_end);

   used = tmp_used;
}

void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr = data;
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s *ptr_end = ptr + used;

   do {
      ptr->print();
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * abbreviation_s
 * source_s
 */

// --- struct string_s_ui_s definition ---

typedef struct string_s_ui_s abbreviation_s;
typedef struct string_s_ui_s source_s;

struct string_s_ui_s
{
   string_s string;
   unsigned number;

   inline void init();
   inline void clear();
   inline void set(string_s &a_string,unsigned a_number);
   inline void flush_all();
   inline void swap(string_s_ui_s &second);
   inline string_s_ui_s &operator=(string_s_ui_s &src);
   inline bool operator==(string_s_ui_s &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
};

// -- struct string_s_ui_s method definition ---

inline void string_s_ui_s::init()
{
   string.init();
}

inline void string_s_ui_s::clear()
{
   string.clear();
}

inline void string_s_ui_s::set(string_s &a_string,unsigned a_number)
{
   string = a_string;
   number = a_number;
}

inline void string_s_ui_s::flush_all()
{
}

inline void string_s_ui_s::swap(string_s_ui_s &second)
{
   string.swap(second.string);

   unsigned tmp_number = number;
   number = second.number;
   second.number = tmp_number;
}

inline string_s_ui_s &string_s_ui_s::operator=(string_s_ui_s &src)
{
   string = src.string;
   number = src.number;

   return *this;
}

inline bool string_s_ui_s::operator==(string_s_ui_s &second)
{
   return (string == second.string && number == second.number);
}

inline unsigned string_s_ui_s::save_size()
{
   return (string.save_size() + sizeof(unsigned));
}

inline void string_s_ui_s::save_to(char **b_ptr)
{
   string.save_to(b_ptr);
   *(unsigned *)*b_ptr = number; *b_ptr += sizeof(unsigned);
}

inline void string_s_ui_s::load_from(char **b_ptr)
{
   string.load_from(b_ptr);
   number = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
}

inline void string_s_ui_s::print()
{
   (&string)->print();
   printf("%d ",*(&number));
}


/*
 * abbreviations_s
 * sources_s
 */

// --- struct string_s_ui_s_a definition ---

typedef struct string_s_ui_s_a abbreviations_s;
typedef struct string_s_ui_s_a sources_s;

struct string_s_ui_s_a
{
   unsigned size;
   unsigned used;
   string_s_ui_s *data;

   inline void init();
   inline void init_size(unsigned a_size);
   void clear();
   void set(unsigned a_used,string_s_ui_s *a_data);
   inline void flush();
   inline void flush_all();
   inline void swap(string_s_ui_s_a &second);
   inline string_s_ui_s &operator[](unsigned a_idx);
   inline string_s_ui_s &__at(unsigned a_idx);
   inline string_s_ui_s &__tail(unsigned a_idx);
   inline string_s_ui_s &__last();
   inline string_s_ui_s &__pop();
   inline void push(string_s_ui_s &a_value);
   inline void push_blank();
   inline void push_clear();
   inline string_s_ui_s &pop();
   inline string_s_ui_s &last();
   void copy_resize(unsigned a_size);
   void fill(string_s_ui_s &a_value);
   unsigned get_idx(string_s_ui_s &a_value);
   string_s_ui_s_a &operator=(string_s_ui_s_a &src);
   bool operator==(string_s_ui_s_a &second);
   unsigned save_size();
   void save_to(char **b_ptr);
   void load_from(char **b_ptr);
   void print();
   unsigned get_idx_by_string(unsigned n_length,char *n_data);
};

// --- struct string_s_ui_s_a method definition ---

inline void string_s_ui_s_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void string_s_ui_s_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

void string_s_ui_s_a::clear()
{
   if (data != NULL) {
      string_s_ui_s *ptr = data;
      string_s_ui_s *ptr_end = ptr + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);

      cfree(data);
   }

   init();
}

void string_s_ui_s_a::set(unsigned a_used,string_s_ui_s *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + a_used;
   string_s_ui_s *a_ptr = a_data;

   do {
      *ptr = *a_ptr;
   } while(++a_ptr,++ptr < ptr_end);
   used = a_used;
}

inline void string_s_ui_s_a::flush()
{
   copy_resize(used);
}

inline void string_s_ui_s_a::flush_all()
{
   copy_resize(used);
}

inline void string_s_ui_s_a::swap(string_s_ui_s_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   string_s_ui_s *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline string_s_ui_s &string_s_ui_s_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline string_s_ui_s &string_s_ui_s_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline string_s_ui_s &string_s_ui_s_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline string_s_ui_s &string_s_ui_s_a::__last()
{
   return data[used - 1];
}

inline string_s_ui_s &string_s_ui_s_a::__pop()
{
   return data[--used];
}

inline void string_s_ui_s_a::push(string_s_ui_s &a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void string_s_ui_s_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void string_s_ui_s_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   data[used].clear();

   used++;
}

inline string_s_ui_s &string_s_ui_s_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline string_s_ui_s &string_s_ui_s_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void string_s_ui_s_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   string_s_ui_s *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (string_s_ui_s *)cmalloc(a_size*sizeof(string_s_ui_s));

      if (a_size > used) {
	 string_s_ui_s *ptr = n_data + used;
	 string_s_ui_s *ptr_end = n_data + a_size;

	 do {
	    ptr->init();
	 } while(++ptr < ptr_end);
      }
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(string_s_ui_s));
   }

   if (size > used) {
      string_s_ui_s *ptr = data + used;
      string_s_ui_s *ptr_end = data + size;

      do {
	 ptr->clear();
      } while(++ptr < ptr_end);
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void string_s_ui_s_a::fill(string_s_ui_s &a_value)
{
   if (size == 0) return;

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned string_s_ui_s_a::get_idx(string_s_ui_s &a_value)
{
   if (used == 0) return c_idx_not_exist;

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

string_s_ui_s_a &string_s_ui_s_a::operator=(string_s_ui_s_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);

   string_s_ui_s *ptr = data;
   string_s_ui_s *s_ptr = src.data;
   string_s_ui_s *s_ptr_end = s_ptr + src.used;

   do {
      *ptr = *s_ptr;
   } while(++ptr,++s_ptr < s_ptr_end);

   used = src.used;
   return *this;
}

bool string_s_ui_s_a::operator==(string_s_ui_s_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + used;
   string_s_ui_s *s_ptr = second.data;

   do {
      if (!(*ptr == *s_ptr)) {
	 return false;
      }
   } while(++s_ptr,++ptr < ptr_end);

   return true;
}

unsigned string_s_ui_s_a::save_size()
{
   if (used == 0) return sizeof(unsigned);
   
   unsigned ret_size = sizeof(unsigned);

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + used;

   do {
      ret_size += ptr->save_size();
   } while(++ptr < ptr_end);

   return ret_size;
}

inline void string_s_ui_s_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + used;

   do {
      ptr->save_to(b_ptr);
   } while(++ptr < ptr_end);
}

void string_s_ui_s_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + tmp_used;

   do {
      ptr->load_from(b_ptr);
   } while(++ptr < ptr_end);

   used = tmp_used;
}

void string_s_ui_s_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   string_s_ui_s *ptr = data;
   string_s_ui_s *ptr_end = ptr + used;

   do {
      ptr->print();
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * lalr_stack_element_s
 */

// --- struct ui_ui_ui_s definition ---

typedef struct ui_ui_ui_s lalr_stack_element_s;

struct ui_ui_ui_s
{
   unsigned first_num;
   unsigned second_num;
   unsigned third_num;

   inline void init();
   inline void clear();
   inline void set(unsigned a_first_num,unsigned a_second_num,unsigned a_third_num);
   inline void flush_all();
   inline void swap(ui_ui_ui_s &second);
   inline ui_ui_ui_s &operator=(ui_ui_ui_s &src);
   inline bool operator==(ui_ui_ui_s &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
};

// -- struct ui_ui_ui_s method definition ---

inline void ui_ui_ui_s::init()
{
}

inline void ui_ui_ui_s::clear()
{
}

inline void ui_ui_ui_s::set(unsigned a_first_num,unsigned a_second_num,unsigned a_third_num)
{
   first_num = a_first_num;
   second_num = a_second_num;
   third_num = a_third_num;
}

inline void ui_ui_ui_s::flush_all()
{
}

inline void ui_ui_ui_s::swap(ui_ui_ui_s &second)
{
   unsigned tmp_first_num = first_num;
   first_num = second.first_num;
   second.first_num = tmp_first_num;

   unsigned tmp_second_num = second_num;
   second_num = second.second_num;
   second.second_num = tmp_second_num;

   unsigned tmp_third_num = third_num;
   third_num = second.third_num;
   second.third_num = tmp_third_num;
}

inline ui_ui_ui_s &ui_ui_ui_s::operator=(ui_ui_ui_s &src)
{
   first_num = src.first_num;
   second_num = src.second_num;
   third_num = src.third_num;

   return *this;
}

inline bool ui_ui_ui_s::operator==(ui_ui_ui_s &second)
{
   return (first_num == second.first_num && second_num == second.second_num && third_num == second.third_num);
}

inline unsigned ui_ui_ui_s::save_size()
{
   return (sizeof(unsigned) + sizeof(unsigned) + sizeof(unsigned));
}

inline void ui_ui_ui_s::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = first_num; *b_ptr += sizeof(unsigned);
   *(unsigned *)*b_ptr = second_num; *b_ptr += sizeof(unsigned);
   *(unsigned *)*b_ptr = third_num; *b_ptr += sizeof(unsigned);
}

inline void ui_ui_ui_s::load_from(char **b_ptr)
{
   first_num = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   second_num = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   third_num = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
}

inline void ui_ui_ui_s::print()
{
   printf("%d ",*(&first_num));
   printf("%d ",*(&second_num));
   printf("%d ",*(&third_num));
}


/*
 * lalr_stack_s
 */

// --- struct ui_ui_ui_s_a definition ---

typedef struct ui_ui_ui_s_a lalr_stack_s;

struct ui_ui_ui_s_a
{
   unsigned size;
   unsigned used;
   ui_ui_ui_s *data;

   inline void init();
   inline void init_size(unsigned a_size);
   inline void clear();
   inline void set(unsigned a_used,ui_ui_ui_s *a_data);
   inline void flush();
   inline void flush_all();
   inline void swap(ui_ui_ui_s_a &second);
   inline ui_ui_ui_s &operator[](unsigned a_idx);
   inline ui_ui_ui_s &__at(unsigned a_idx);
   inline ui_ui_ui_s &__tail(unsigned a_idx);
   inline ui_ui_ui_s &__last();
   inline ui_ui_ui_s &__pop();
   inline void push(ui_ui_ui_s &a_value);
   inline void push_blank();
   inline void push_clear();
   inline ui_ui_ui_s &pop();
   inline ui_ui_ui_s &last();
   void copy_resize(unsigned a_size);
   void fill(ui_ui_ui_s &a_value);
   unsigned get_idx(ui_ui_ui_s &a_value);
   inline ui_ui_ui_s_a &operator=(ui_ui_ui_s_a &src);
   inline bool operator==(ui_ui_ui_s_a &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   void print();
   inline void push(unsigned a_first_num);
   inline void push(unsigned a_first_num,unsigned a_second_num,unsigned a_third_num);
};

// --- struct ui_ui_ui_s_a method definition ---

inline void ui_ui_ui_s_a::init()
{
   size = 0;
   used = 0;
   data = NULL;
}

inline void ui_ui_ui_s_a::init_size(unsigned a_size)
{
   init();
   copy_resize(a_size);
}

inline void ui_ui_ui_s_a::clear()
{
   if (data != NULL) {
      cfree(data);
   }

   init();
}

inline void ui_ui_ui_s_a::set(unsigned a_used,ui_ui_ui_s *a_data)
{
   clear();
   if (a_used == 0) return;

   debug_assert(a_data != NULL);
   copy_resize(a_used);

   memcpy(data,a_data,a_used*sizeof(ui_ui_ui_s));
   used = a_used;
}

inline void ui_ui_ui_s_a::flush()
{
   copy_resize(used);
}

inline void ui_ui_ui_s_a::flush_all()
{
   copy_resize(used);
}

inline void ui_ui_ui_s_a::swap(ui_ui_ui_s_a &second)
{
   unsigned tmp_size = size;
   size = second.size;
   second.size = tmp_size;

   unsigned tmp_used = used;
   used = second.used;
   second.used = tmp_used;

   ui_ui_ui_s *tmp_data = data;
   data = second.data;
   second.data = tmp_data;
}

inline ui_ui_ui_s &ui_ui_ui_s_a::operator[](unsigned a_idx)
{
   debug_assert(a_idx < used);
   return data[a_idx];
}

inline ui_ui_ui_s &ui_ui_ui_s_a::__at(unsigned a_idx)
{
   return data[a_idx];
}

inline ui_ui_ui_s &ui_ui_ui_s_a::__tail(unsigned a_idx)
{
   return data[used - 1 - a_idx];
}

inline ui_ui_ui_s &ui_ui_ui_s_a::__last()
{
   return data[used - 1];
}

inline ui_ui_ui_s &ui_ui_ui_s_a::__pop()
{
   return data[--used];
}

inline void ui_ui_ui_s_a::push(ui_ui_ui_s &a_value)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }
   
   data[used++] = a_value;
}

inline void ui_ui_ui_s_a::push_blank()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline void ui_ui_ui_s_a::push_clear()
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   used++;
}

inline ui_ui_ui_s &ui_ui_ui_s_a::pop()
{
   debug_assert(used > 0);
   return data[--used];
}

inline ui_ui_ui_s &ui_ui_ui_s_a::last()
{
   debug_assert(used != 0);
   return data[used - 1];
}

void ui_ui_ui_s_a::copy_resize(unsigned a_size)
{
   debug_assert(a_size >= used);

   ui_ui_ui_s *n_data;

   if (a_size == 0) {
      n_data = NULL;
   }
   else {
      n_data = (ui_ui_ui_s *)cmalloc(a_size*sizeof(ui_ui_ui_s));
   }

   if (used != 0) {
      memcpy(n_data,data,used*sizeof(ui_ui_ui_s));
   }

   if (size != 0) {
      cfree(data);
   }

   data = n_data;
   size = a_size;
}

void ui_ui_ui_s_a::fill(ui_ui_ui_s &a_value)
{
   if (size == 0) return;

   ui_ui_ui_s *ptr = data;
   ui_ui_ui_s *ptr_end = ptr + size;

   do {
      *ptr = a_value;
   } while(++ptr < ptr_end);

   used = size;
}

unsigned ui_ui_ui_s_a::get_idx(ui_ui_ui_s &a_value)
{
   if (used == 0) return c_idx_not_exist;

   ui_ui_ui_s *ptr = data;
   ui_ui_ui_s *ptr_end = ptr + used;

   do {
      if (*ptr == a_value) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

inline ui_ui_ui_s_a &ui_ui_ui_s_a::operator=(ui_ui_ui_s_a &src)
{
   clear();

   if (src.used == 0) return *this;
   
   copy_resize(src.used);
   memcpy(data,src.data,src.used*sizeof(ui_ui_ui_s));

   used = src.used;
   return *this;
}

inline bool ui_ui_ui_s_a::operator==(ui_ui_ui_s_a &second)
{
   if (used != second.used) return false;
   if (used == 0) return true;

   return (memcmp(data,second.data,used*sizeof(ui_ui_ui_s)) == 0);
}

inline unsigned ui_ui_ui_s_a::save_size()
{
   return sizeof(unsigned) + used*sizeof(ui_ui_ui_s);
}

inline void ui_ui_ui_s_a::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);

   if (used == 0) return;

   unsigned data_size = used*sizeof(ui_ui_ui_s);
   memcpy(*b_ptr,data,data_size);
   *b_ptr += data_size;
}

inline void ui_ui_ui_s_a::load_from(char **b_ptr)
{
   clear();

   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   if (tmp_used == 0) return;

   copy_resize(tmp_used);

   unsigned data_size = tmp_used*sizeof(ui_ui_ui_s);
   memcpy(data,*b_ptr,data_size);

   *b_ptr += data_size;
   used = tmp_used;
}

void ui_ui_ui_s_a::print()
{
   if (used == 0) {
      printf("empty");
      return;
   }

   ui_ui_ui_s *ptr = data;
   ui_ui_ui_s *ptr_end = ptr + used;

   do {
      ptr->print();
   putchar('\n');
   } while(++ptr < ptr_end);
}


/*
 * process_s
 */

// --- struct ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s definition ---

typedef struct ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s process_s;

struct ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s
{
   unsigned processor_ptr;
   string_s source_string;
   unsigned source_idx;
   ui_ui_ui_s_a lalr_stack;
   string_s_a_a cont_params;

   inline void init();
   inline void clear();
   inline void set(unsigned a_processor_ptr,string_s &a_source_string,unsigned a_source_idx,ui_ui_ui_s_a &a_lalr_stack,string_s_a_a &a_cont_params);
   inline void flush_all();
   inline void swap(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &second);
   inline ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &operator=(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &src);
   inline bool operator==(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
   unsigned final_automata_recognize(string_s &source_string,unsigned &input_idx,unsigned &line_cnt);
   void parse_def_code(string_s &def_code);
   void run_on(char *file_name);
};

// -- struct ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s method definition ---

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::init()
{
   source_string.init();
   lalr_stack.init();
   cont_params.init();
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::clear()
{
   source_string.clear();
   lalr_stack.clear();
   cont_params.clear();
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::set(unsigned a_processor_ptr,string_s &a_source_string,unsigned a_source_idx,ui_ui_ui_s_a &a_lalr_stack,string_s_a_a &a_cont_params)
{
   processor_ptr = a_processor_ptr;
   source_string = a_source_string;
   source_idx = a_source_idx;
   lalr_stack = a_lalr_stack;
   cont_params = a_cont_params;
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::flush_all()
{
   lalr_stack.flush_all();
   cont_params.flush_all();
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::swap(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &second)
{
   unsigned tmp_processor_ptr = processor_ptr;
   processor_ptr = second.processor_ptr;
   second.processor_ptr = tmp_processor_ptr;

   source_string.swap(second.source_string);

   unsigned tmp_source_idx = source_idx;
   source_idx = second.source_idx;
   second.source_idx = tmp_source_idx;

   lalr_stack.swap(second.lalr_stack);

   cont_params.swap(second.cont_params);
}

inline ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::operator=(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &src)
{
   processor_ptr = src.processor_ptr;
   source_string = src.source_string;
   source_idx = src.source_idx;
   lalr_stack = src.lalr_stack;
   cont_params = src.cont_params;

   return *this;
}

inline bool ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::operator==(ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s &second)
{
   return (processor_ptr == second.processor_ptr && source_string == second.source_string && source_idx == second.source_idx && lalr_stack == second.lalr_stack && cont_params == second.cont_params);
}

inline unsigned ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::save_size()
{
   return (sizeof(unsigned) + source_string.save_size() + sizeof(unsigned) + lalr_stack.save_size() + cont_params.save_size());
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::save_to(char **b_ptr)
{
   *(unsigned *)*b_ptr = processor_ptr; *b_ptr += sizeof(unsigned);
   source_string.save_to(b_ptr);
   *(unsigned *)*b_ptr = source_idx; *b_ptr += sizeof(unsigned);
   lalr_stack.save_to(b_ptr);
   cont_params.save_to(b_ptr);
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::load_from(char **b_ptr)
{
   processor_ptr = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   source_string.load_from(b_ptr);
   source_idx = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);
   lalr_stack.load_from(b_ptr);
   cont_params.load_from(b_ptr);
}

inline void ui_string_s_ui_ui_ui_ui_s_a_string_s_a_a_s::print()
{
   printf("%d ",*(&processor_ptr));
   (&source_string)->print();
   printf("%d ",*(&source_idx));
   (&lalr_stack)->print();
   (&cont_params)->print();
}


/*
 * processor_s
 */

// --- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s definition ---

typedef struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s processor_s;

struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s
{
   ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a data_types;
   string_s_ui_s_a abbreviations;

   inline void init();
   inline void clear();
   inline void set(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &a_data_types,string_s_ui_s_a &a_abbreviations);
   inline void flush_all();
   inline void swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &second);
   inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &src);
   inline bool operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &second);
   inline unsigned save_size();
   inline void save_to(char **b_ptr);
   inline void load_from(char **b_ptr);
   inline void print();
   void data_type_print(char *spaces,unsigned type_idx,char *var_name);
   void generate_array_type(string_arrays_s &params);
   void generate_array_inlines(unsigned a_dt_idx);
   void generate_array_methods(unsigned a_dt_idx);
   void generate_queue_type(string_arrays_s &params);
   void generate_queue_inlines(unsigned a_dt_idx);
   void generate_queue_methods(unsigned a_dt_idx);
   void generate_struct_type(string_arrays_s &params);
   void generate_struct_inlines(unsigned a_dt_idx);
   void generate_struct_methods(unsigned a_dt_idx);
   void generate_container_def(string_s &cont_name,string_arrays_s &cont_params);
   void generate_type_inlines(unsigned a_length,char *a_data);
   void generate_type_methods(unsigned a_length,char *a_data);
   void init_processor();
   void run(char *file_name);
   void save_data(char *file_name);
   void load_and_merge_data(char *file_name);
};

// -- struct ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s method definition ---

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::init()
{
   data_types.init();
   abbreviations.init();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::clear()
{
   data_types.clear();
   abbreviations.clear();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::set(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a &a_data_types,string_s_ui_s_a &a_abbreviations)
{
   data_types = a_data_types;
   abbreviations = a_abbreviations;
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::flush_all()
{
   data_types.flush_all();
   abbreviations.flush_all();
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::swap(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &second)
{
   data_types.swap(second.data_types);

   abbreviations.swap(second.abbreviations);
}

inline ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::operator=(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &src)
{
   data_types = src.data_types;
   abbreviations = src.abbreviations;

   return *this;
}

inline bool ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::operator==(ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s &second)
{
   return (data_types == second.data_types && abbreviations == second.abbreviations);
}

inline unsigned ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::save_size()
{
   return (data_types.save_size() + abbreviations.save_size());
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::save_to(char **b_ptr)
{
   data_types.save_to(b_ptr);
   abbreviations.save_to(b_ptr);
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::load_from(char **b_ptr)
{
   data_types.load_from(b_ptr);
   abbreviations.load_from(b_ptr);
}

inline void ui_string_s_ui_string_s_a_string_s_a_ui_a_s_a_string_s_ui_s_a_s::print()
{
   (&data_types)->print();
   (&abbreviations)->print();
}




/*
 * TODO list
 *
 * - jednotlive funkce generujici kontejnery - done: array,set
 * - promyslet zda nezvetsovat dynamicke kontejnery na dvojnasobek soucasne velikosti
 * - mozna u save_to kontrolovat hranice tejne jako u load_from
 *
 */

#define STRUCT_NAME data_type.string.data
#define TYPE_CNT type_cnt
#define TYPE_NAME type.string.data
#define TYPE_NUMBER type.number
#define TYPE_NAMES(IDX) (types[IDX]->string.data)
#define TYPE_NUMBERS(IDX) (types[IDX]->number)
#define VAR_NAMES(IDX) (data_type.vars[IDX].data)
#define COMP_IDX_CNT (data_type.compare_idxs.used)
#define COMP_IDXS(IDX) (data_type.compare_idxs[IDX])

/*
 * typy parametru containeru
 */

enum {
   c_param_types = 0,
   c_param_variables,
   c_param_compare,
   c_param_functions,
   c_param_names,
};

/*
 * retezce popisujici zacatek a konec definicniho bloku
 */

const char *c_begin = "@""begin";
const char *c_end = "@""end";

const unsigned c_begin_len = strlen(c_begin);
const unsigned c_end_len = strlen(c_end);

/*
 * vycet datovych typu
 */

enum {
   c_type_basic = 0x00000001,
   c_type_static = 0x00000002,
   c_type_dynamic = 0x00000004,
};

const unsigned c_type_flushable = 0x00000008;
const unsigned c_type_part_comparable = 0x00000010;

/*
 * jmena zakladnich datovych typu
 */
enum {
   c_bt_bool = 0,
   c_bt_char,
   c_bt_unsigned_char,
   c_bt_short,
   c_bt_unsigned_short,
   c_bt_int,
   c_bt_unsigned,
   c_bt_long,
   c_bt_unsigned_long,
   c_bt_long_long,
   c_bt_unsigned_long_long,
   c_bt_float,
   c_bt_double,
   c_bt_long_double,
   c_bt_pthread_t,
};

const unsigned c_basic_type_cnt = 18;
const char *c_basic_types[c_basic_type_cnt] = {
   "bb",
   "bc",
   "uc",
   "si",
   "usi",
   "bi",
   "ui",
   "li",
   "uli",
   "lli",
   "ulli",
   "bf",
   "bd",
   "ld",
   "pthread_t",
   "mutex_s",
   "string_s",
   "img_3ub_s",
};

unsigned c_basic_type_types[c_basic_type_cnt] = {
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_basic,
   c_type_dynamic,
   c_type_dynamic,
   c_type_dynamic,
};

/*
 * "zkratky" zakladnich datovych typu
 */
const unsigned c_basic_abbreviation_cnt = 39;
const char *c_basic_abbreviations[c_basic_abbreviation_cnt] = {
   "bb","bool",
   "bc","char",
   "uc","unsigned_char",
   "si","short","short_int",
   "usi","unsigned_short","unsigned_short_int",
   "bi","int",
   "ui","unsigned","unsigned_int",
   "li","long","long_int",
   "uli","unsigned_long","unsigned_long_int",
   "lli","long_long","long_long_int",
   "ulli","unsigned_long_long","unsigned_long_long_int",
   "bf","float",
   "bd","double",
   "ld","long_double",
   "pthread_t",
   "mutex_s",
   "string_s",
   "img_3ub_s",
};

const int c_basic_abbreviation_types[c_basic_abbreviation_cnt] = {
   0,0,
   1,1,
   2,2,
   3,3,3,
   4,4,4,
   5,5,
   6,6,6,
   7,7,7,
   8,8,8,
   9,9,9,
   10,10,10,
   11,11,
   12,12,
   13,13,
   14,
   15,
   16,
   17,
};

/*
 * konstanty popisujici kontejnery
 */

const unsigned c_cont_cnt = 3;

enum {
   c_cont_array = 0,
   c_cont_queue,
   c_cont_struct,
};

const char *c_cont_names[c_cont_cnt] = {
   "array",
   "queue",
   "struct",
};

const char *c_cont_postfixes[c_cont_cnt] = {
   "_a",
   "_q",
   "_s",
};

/*
 * funkce struktury abbreviation_s
 */

unsigned abbreviations_s::get_idx_by_string(unsigned n_length,char *n_data)
{
   if (used == 0) return c_idx_not_exist;

   abbreviation_s *ptr = data;
   abbreviation_s *ptr_end = ptr + used;
   do {
      if (ptr->string.compare_char_ptr(n_length,n_data)) {
	 return ptr - data;
      }
   } while(++ptr < ptr_end);

   return c_idx_not_exist;
}

/*
 * funkce struktury processor_s
 */

void processor_s::data_type_print(char *spaces,unsigned type_idx,char *var_name)
{
   data_type_s &type = data_types[type_idx];

   if (type.number & c_type_basic) {
      switch (type_idx) {
      case c_bt_bool:
printf(
"%sif(%s) {\n"
"%s   printf(\"true\");\n"
"%s}\n"
"%selse {\n"
"%s   printf(\"false\");\n"
"%s}\n"
,spaces,var_name,spaces,spaces,spaces,spaces,spaces);
	 break;
      case c_bt_char:
printf(
"%sputchar(%s);\n"
,spaces,var_name);
	 break;
      case c_bt_unsigned_char:
printf(
"%sprintf(\"%%hhu\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_short:
printf(
"%sprintf(\"%%hd\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_unsigned_short:
printf(
"%sprintf(\"%%hu\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_int:
printf(
"%sprintf(\"%%d\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_unsigned:
printf(
"%sprintf(\"%%u\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_long:
printf(
"%sprintf(\"%%ld\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_unsigned_long:
printf(
"%sprintf(\"%%lu\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_long_long:
printf(
"%sprintf(\"%%lld\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_unsigned_long_long:
printf(
"%sprintf(\"%%llu\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_float:
printf(
"%sprintf(\"%%f\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_double:
printf(
"%sprintf(\"%%f\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_long_double:
printf(
"%sprintf(\"%%Lf\",%s);\n"
,spaces,var_name);
	 break;
      case c_bt_pthread_t:
printf(
"%sprintf(\"%%d\",(int)%s);\n"
,spaces,var_name);
	 break;
      default:
	 assert(0);
      }
   }
   else {
printf(
"%s%s.print();\n"
,spaces,var_name);
   }
}


#define ARRAY_INIT() \
{\
printf(\
"inline void %s::init()\n"\
"{\n"\
"   size = 0;\n"\
"   used = 0;\n"\
"   data = NULL;\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define ARRAY_INIT_SIZE() \
{\
printf(\
"inline void %s::init_size(unsigned a_size)\n"\
"{\n"\
"   init();\n"\
"   copy_resize(a_size);\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define ARRAY_CLEAR() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::clear()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::clear()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   if (data != NULL) {\n"\
);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"      %s *ptr = data;\n"\
"      %s *ptr_end = ptr + size;\n"\
"      \n"\
"      do {\n"\
"         ptr->clear();\n"\
"      } while(++ptr < ptr_end);\n"\
"      \n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"      cfree(data);\n"\
"   }\n"\
"\n"\
"   init();\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_SET() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::set(unsigned a_used,%s *a_data)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"void %s::set(unsigned a_used,%s *a_data)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
printf(\
"{\n"\
"   clear();\n"\
"   if (a_used == 0) return;\n"\
"   \n"\
"   debug_assert(a_data != NULL);\n"\
"   copy_resize(a_used);\n"\
"\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   memcpy(data,a_data,a_used*sizeof(%s));\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + a_used;\n"\
"   %s *a_ptr = a_data;\n"\
"\n"\
"   do {\n"\
"      *ptr = *a_ptr;\n"\
"   } while(++a_ptr,++ptr < ptr_end);\n"\
"\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   used = a_used;\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_FLUSH() \
{\
printf(\
"inline void %s::flush()\n"\
"{\n"\
"   copy_resize(used);\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define ARRAY_FLUSH_ALL() \
{\
   if (!(TYPE_NUMBER & c_type_flushable)) {\
printf(\
"inline void %s::flush_all()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::flush_all()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
);\
   if (TYPE_NUMBER & c_type_flushable) {\
printf(\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"\n"\
"   do {\n"\
"      ptr->flush_all();\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   copy_resize(used);\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_SWAP() \
{\
printf(\
"inline void %s::swap(%s &second)\n"\
"{\n"\
"   unsigned tmp_unsigned = size;\n"\
"   size = second.size;\n"\
"   second.size = tmp_unsigned;\n"\
"\n"\
"   tmp_unsigned = used;\n"\
"   used = second.used;\n"\
"   second.used = tmp_unsigned;\n"\
"\n"\
"   %s *tmp_data = data;\n"\
"   data = second.data;\n"\
"   second.data = tmp_data;\n"\
"}\n"\
"\n"\
,STRUCT_NAME,STRUCT_NAME,TYPE_NAME);\
}

#define ARRAY_OPERATOR_LE_BR_RE_BR() \
{\
printf(\
"inline %s &%s::operator[](unsigned a_idx)\n"\
"{\n"\
"   debug_assert(a_idx < used);\n"\
"   return data[a_idx];\n"\
"}\n"\
"\n"\
,TYPE_NAME,STRUCT_NAME);\
}

#define ARRAY_PUSH() \
{\
   if (TYPE_NUMBER & c_type_basic) {\
printf(\
"inline void %s::push(%s a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"inline void %s::push(%s &a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
printf(\
"{\n"\
"   if (used >= size) {\n"\
"      copy_resize((size << 1) + c_array_add);\n"\
"   }\n"\
"\n"\
"   data[used++] = a_value;\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_PUSH_BLANK() \
{\
printf(\
"inline void %s::push_blank()\n"\
"{\n"\
"   if (used >= size) {\n"\
"      copy_resize((size << 1) + c_array_add);\n"\
"   }\n"\
"\n"\
"   used++;\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define ARRAY_PUSH_CLEAR() \
{\
printf(\
"inline void %s::push_clear()\n"\
"{\n"\
"   if (used >= size) {\n"\
"      copy_resize((size << 1) + c_array_add);\n"\
"   }\n"\
"\n"\
,STRUCT_NAME);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   used++;\n"\
);\
   }\
   else {\
printf(\
"   data[used++].clear();\n"\
);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define ARRAY_POP() \
{\
printf(\
"inline %s &%s::pop()\n"\
"{\n"\
"   debug_assert(used > 0);\n"\
"   return data[--used];\n"\
"}\n"\
"\n"\
,TYPE_NAME,STRUCT_NAME);\
}

#define ARRAY_LAST() \
{\
printf(\
"inline %s &%s::last()\n"\
"{\n"\
"   debug_assert(used > 0);\n"\
"   return data[used - 1];\n"\
"}\n"\
"\n"\
,TYPE_NAME,STRUCT_NAME);\
}

#define ARRAY_COPY_RESIZE() \
{\
printf(\
"void %s::copy_resize(unsigned a_size)\n"\
"{\n"\
"   debug_assert(a_size >= used);\n"\
"\n"\
"   %s *n_data;\n"\
"\n"\
"   if (a_size == 0) {\n"\
"      n_data = NULL;\n"\
"   }\n"\
"   else {\n"\
"      n_data = (%s *)cmalloc(a_size*sizeof(%s));\n"\
,STRUCT_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"\n"\
"      if (a_size > used) {\n"\
"         %s *ptr = n_data + used;\n"\
"         %s *ptr_end = n_data + a_size;\n"\
"\n"\
"         do {\n"\
"            ptr->init();\n"\
"         } while(++ptr < ptr_end);\n"\
"      }\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   }\n"\
"\n"\
"   if (used != 0) {\n"\
"      memcpy(n_data,data,used*sizeof(%s));\n"\
"   }\n"\
,TYPE_NAME);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"\n"\
"   if (size > used) {\n"\
"      %s *ptr = data + used;\n"\
"      %s *ptr_end = data + size;\n"\
"\n"\
"      do {\n"\
"	 ptr->clear();\n"\
"      } while(++ptr < ptr_end);\n"\
"   }\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"\n"\
"   if (size != 0) {\n"\
"      cfree(data);\n"\
"   }\n"\
"\n"\
"   data = n_data;\n"\
"   size = a_size;\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_FILL() \
{\
   if (type_idx == c_bt_char){\
printf(\
"inline void %s::fill(%s a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
   else {\
      if (TYPE_NUMBER & c_type_basic) {\
printf(\
"void %s::fill(%s a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
      }\
      else {\
printf(\
"void %s::fill(%s &a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
      }\
   }\
printf(\
"{\n"\
"   if (size == 0) return;\n"\
"\n"\
);\
   if (type_idx == c_bt_char) {\
printf(\
"   memset(data,a_value,size);\n"\
);\
   }\
   else {\
printf(\
"   %s *ptr = data;\n"\
"   %s *ptr_end = data + size;\n"\
"\n"\
"   do {\n"\
"      *ptr = a_value;\n"\
"   } while(++ptr < ptr_end);\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"\n"\
"   used = size;\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_GET_IDX() \
{\
   if (TYPE_NUMBER & c_type_basic) {\
printf(\
"unsigned %s::get_idx(%s a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"unsigned %s::get_idx(%s &a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
printf(\
"{\n"\
"   if (used == 0) return c_idx_not_exist;\n"\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = data + used;\n"\
"\n"\
"   do {\n"\
"      if (*ptr == a_value) {\n"\
"	 return ptr - data;\n"\
"      }\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   return c_idx_not_exist;\n"\
"}\n"\
"\n"\
,TYPE_NAME,TYPE_NAME);\
}

#define ARRAY_GET_PC_IDX() \
{\
   if (TYPE_NUMBER & c_type_part_comparable) {\
printf(\
"unsigned %s::get_pc_idx(%s &a_value)\n"\
"{\n"\
"   if (used == 0) return c_idx_not_exist;\n"\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = data + used;\n"\
"\n"\
"   do {\n"\
"      if (ptr->part_compare(a_value)) {\n"\
"	 return ptr - data;\n"\
"      }\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   return c_idx_not_exist;\n"\
"}\n"\
"\n"\
,STRUCT_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
}

#define ARRAY_OPERATOR_EQUAL() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline %s &%s::operator=(%s &src)\n"\
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);\
   }\
   else {\
printf(\
"%s &%s::operator=(%s &src)\n"\
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   clear();\n"\
"\n"\
"   if (src.used == 0) return *this;\n"\
"\n"\
"   copy_resize(src.used);\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   memcpy(data,src.data,src.used*sizeof(%s));\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"\n"\
"   %s *ptr = data;\n"\
"   %s *s_ptr = src.data;\n"\
"   %s *s_ptr_end = s_ptr + src.used;\n"\
"\n"\
"   do {\n"\
"      *ptr = *s_ptr;\n"\
"   } while(++ptr,++s_ptr < s_ptr_end);\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"\n"\
"   used = src.used;\n"\
"   return *this;\n"\
"}\n"\
"\n"\
);\
}

#define ARRAY_OPERATOR_DOUBLE_EQUAL() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline bool %s::operator==(%s &second)\n"\
,STRUCT_NAME,STRUCT_NAME);\
   }\
   else {\
printf(\
"bool %s::operator==(%s &second)\n"\
,STRUCT_NAME,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   if (used != second.used) return false;\n"\
"   if (used == 0) return true;\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"\n"\
"   return (memcmp(data,second.data,used*sizeof(%s)) == 0);\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"   %s *s_ptr = second.data;\n"\
"\n"\
"   do {\n"\
"      if (!(*ptr == *s_ptr)) {\n"\
"	 return false;\n"\
"      }\n"\
"   } while(++s_ptr,++ptr < ptr_end);\n"\
"\n"\
"   return true;\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define ARRAY_SAVE_SIZE() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline unsigned %s::save_size()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"unsigned %s::save_size()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   return sizeof(unsigned) + used*sizeof(%s);\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"   if (used == 0) return sizeof(unsigned);\n"\
"\n"\
"   unsigned ret_size = sizeof(unsigned);\n"\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"\n"\
"   do {\n"\
"      ret_size += ptr->save_size();\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   return ret_size;\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define ARRAY_SAVE_TO() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::save_to(char **b_ptr)\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::save_to(char **b_ptr)\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   *(unsigned *)b_ptr = used; *b_ptr += sizeof(unsigned);\n"\
"\n"\
"   if (used == 0) return;\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"\n"\
"   unsigned data_size = used*sizeof(%s);\n"\
"   memcpy(*b_ptr,data,data_size);\n"\
"   *b_ptr += data_size;\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"\n"\
"   do {\n"\
"      ptr->save_to(b_ptr);\n"\
"   } while(++ptr < ptr_end);\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define ARRAY_LOAD_FROM() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::load_from(char **b_ptr,char *b_ptr_end)\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::load_from(char **b_ptr,char *b_ptr_end)\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   clear();\n"\
"\n"\
"   assert(*b_ptr + sizeof(unsigned) <= b_ptr_end);\n"\
"   unsigned tmp_used = *(unsigned *)b_ptr; *b_ptr += sizeof(unsigned);\n"\
"   if (tmp_used == 0) return;\n"\
"\n"\
"   copy_resize(tmp_used);\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"\n"\
"   unsigned data_size = tmp_used*sizeof(%s);\n"\
"   assert(*b_ptr + data_size <= b_ptr_end);\n"\
"   memcpy(data,*b_ptr,data_size);\n"\
"\n"\
"   *b_ptr += data_size;\n"\
"   used = tmp_used;\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + tmp_used;\n"\
"\n"\
"   do {\n"\
"      ptr->load_from(b_ptr,b_ptr_end);\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   used = tmp_used;\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define ARRAY_PRINT() \
{\
printf(\
"void %s::print()\n"\
"{\n"\
"   if (used == 0) {\n"\
"      printf(\"empty\");\n"\
"      return;\n"\
"   }\n"\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"\n"\
"   do {\n"\
,STRUCT_NAME,TYPE_NAME,TYPE_NAME);\
   data_type_print("      ",type_idx,"(*ptr)");\
printf(\
"   } while(++ptr < ptr_end);\n"\
"}\n"\
"\n"\
);\
}

void processor_s::generate_array_type(string_arrays_s &params)
{
   string_array_s &type_names = params[c_param_types];
   string_array_s &fun_defs = params[c_param_functions];
   string_array_s &abbs = params[c_param_names];

   assert(type_names.used == 1);

   unsigned abb_idx = abbreviations.get_idx_by_string(type_names[0].size - 1,type_names[0].data);
   assert(abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[abb_idx].number;
   data_type_s &type = data_types[type_idx];

   string_s data_type_name;
   data_type_name.init();
   data_type_name.conc_set(type.string.size - 1,type.string.data,strlen(c_cont_postfixes[c_cont_array]),(char *)c_cont_postfixes[c_cont_array]);

   unsigned data_type_idx;

   if ((data_type_idx = abbreviations.get_idx_by_string(data_type_name.size - 1,data_type_name.data)) == c_idx_not_exist) {
      abbreviations.push_blank();
      abbreviations.last().set(data_type_name,data_types.used);

      data_types.push_blank();
      data_type_s &data_type = data_types.last();

      data_type.cont_idx = c_cont_array;
      data_type.string.swap(data_type_name);
      data_type.number = c_type_dynamic | c_type_flushable;
      data_type.types.push(type.string);

      data_type_idx = data_types.used - 1;
   }
   else {
      //data_type_idx = abbreviations[data_type_idx].number;
      assert(0);
   }

   data_type_name.clear();

   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
	 string_s &abb = abbs[idx];

	 assert(abbreviations.get_idx_by_string(abb.size - 1,abb.data) == c_idx_not_exist);
	 abbreviations.push_blank();
	 abbreviations.last().set(abb,data_type_idx);
      } while(++idx < abbs.used);
   }

   data_type_s &data_type = data_types[data_type_idx];

   // - --- definice struktury array --- -

printf(
"// --- struct %s definition --- \n"
"\n"
,STRUCT_NAME);

   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
printf(
"typedef struct %s %s;\n"
,STRUCT_NAME,abbs[idx].data);
      } while(++idx < abbs.used);
printf(
"\n"
);
   }

printf(
"struct %s\n"
"{\n"
"   unsigned size;\n"
"   unsigned used;\n"
"   %s *data;\n"
"\n"
,STRUCT_NAME,TYPE_NAME);
printf(
"   inline void init();\n"
"   inline void init_size(unsigned a_size);\n"
);
   if (!(TYPE_NUMBER & c_type_dynamic)) {
printf(
"   inline void clear();\n"
"   inline void set(unsigned a_used,%s *a_data);\n"
,TYPE_NAME);
   }
   else {
printf(
"   void clear();\n"
"   void set(unsigned a_used,%s *a_data);\n"
,TYPE_NAME);
   }
printf(
"   inline void flush();\n"
);
   if (!(TYPE_NUMBER & c_type_flushable)) {
printf(
"   inline void flush_all();\n"
);
   }
   else {
printf(
"   void flush_all();\n"
);
   }
printf(
"   inline void swap(%s &second);\n"
"   inline %s &operator[](unsigned a_idx);\n"
,STRUCT_NAME,TYPE_NAME);
   if (TYPE_NUMBER & c_type_basic) {
printf(
"   inline void push(%s a_value);\n"
,TYPE_NAME);
   }
   else {
printf(
"   inline void push(%s &a_value);\n"
,TYPE_NAME);
   }
printf(
"   inline void push_blank();\n"
"   inline void push_clear();\n"
"   inline %s &pop();\n"
"   inline %s &last();\n"
"   void copy_resize(unsigned a_size);\n"
,TYPE_NAME,TYPE_NAME);
   if (type_idx == c_bt_char) {
printf(
"   inline void fill(%s a_value);\n"
,TYPE_NAME);
   }
   else {
      if (TYPE_NUMBER & c_type_basic) {
printf(
"   void fill(%s a_value);\n"
,TYPE_NAME);
      }
      else {
printf(
"   void fill(%s &a_value);\n"
,TYPE_NAME);
      }
   }
   if (TYPE_NUMBER & c_type_basic) {
printf(
"   unsigned get_idx(%s a_value);\n"
,TYPE_NAME);
   }
   else {
printf(
"   unsigned get_idx(%s &a_value);\n"
,TYPE_NAME);
   }
   if (TYPE_NUMBER & c_type_part_comparable) {
printf(
"   unsigned get_pc_idx(%s &a_value);\n"
,TYPE_NAME);
   }
   if (!(TYPE_NUMBER & c_type_dynamic)) {
printf(
"   inline %s &operator=(%s &src);\n"
"   inline bool operator==(%s &second);\n"
//"   inline unsigned save_size();\n"
//"   inline void save_to(char **b_ptr);\n"
//"   inline void load_from(char **b_ptr,char *b_ptr_end);\n"
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);
   }
   else {
printf(
"   %s &operator=(%s &src);\n"
"   bool operator==(%s &second);\n"
//"   unsigned save_size();\n"
//"   void save_to(char **b_ptr);\n"
//"   void load_from(char **b_ptr,char *b_ptr_end);\n"
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);
   }
//printf(
//"   void print();\n"
//);
   if (fun_defs.used != 0) {
      unsigned f_idx = 0;
      do {
printf(
"   %s\n"
,fun_defs[f_idx].data);
      } while(++f_idx < fun_defs.used);
   }
printf(
"};\n"
"\n"
);
};

void processor_s::generate_array_inlines(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   string_s &type_abb_string = data_type.types[0];
   unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
   assert(type_abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[type_abb_idx].number;
   data_type_s &type = data_types[type_idx];

   // --- definice inline funkci ---

printf(
"// --- struct %s inline method definition ---\n"
"\n"
,STRUCT_NAME);

   // - array init method -
ARRAY_INIT();

   // - array init_size method -
ARRAY_INIT_SIZE();

   // - array clear method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_CLEAR();
   }

   // - array set method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_SET();
   }

   // - array_flush_method -
ARRAY_FLUSH();

   // - array flush_all method -
   if (!(TYPE_NUMBER & c_type_flushable)) {
ARRAY_FLUSH_ALL();
   }

   // - array swap method -
ARRAY_SWAP();

   // - array operator[] method -
ARRAY_OPERATOR_LE_BR_RE_BR();

   // - array push method -
ARRAY_PUSH();

   // - array push_blank method -
ARRAY_PUSH_BLANK();

   // - array push_clear method -
ARRAY_PUSH_CLEAR();

   // - array pop method -
ARRAY_POP();

   // - array last method -
ARRAY_LAST();

   // - array copy_resize method -

   // - array fill method -
   if (type_idx == c_bt_char) {
ARRAY_FILL();   
   }

   // - array get_idx method -

   // - array get_pc_idx -

   // - array operator= method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_OPERATOR_EQUAL();
   }

   // - array operator== method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_OPERATOR_DOUBLE_EQUAL();
   }

   // - array save_size method -
   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_SAVE_SIZE();
   }*/

   // - array save_to method -
   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_SAVE_TO();
   }*/

   // - array load_from method -
   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
ARRAY_LOAD_FROM();
   }*/

   // - array print method -
}

void processor_s::generate_array_methods(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   string_s &type_abb_string = data_type.types[0];
   unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
   assert(type_abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[type_abb_idx].number;
   data_type_s &type = data_types[type_idx];

   // --- definice funkci ---

printf(
"// --- struct %s method definition ---\n"
"\n"
,STRUCT_NAME);

   // - array init method -

   // - array init_size method -

   // - array clear method -
   if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_CLEAR();
   }

   // - array set method -
   if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_SET();
   }

   // - array_flush_method -

   // - array flush_all method -
   if (TYPE_NUMBER & c_type_flushable) {
ARRAY_FLUSH_ALL();
   }

   // - array swap method -

   // - array operator[] method -

   // - array push method -

   // - array push_blank method -

   // - array push_clear method -

   // - array pop method -

   // - array last method -

   // - array copy_resize method -
ARRAY_COPY_RESIZE();

   // - array fill method -
   if (type_idx != c_bt_char) {
ARRAY_FILL();   
   }

   // - array get_idx method -
ARRAY_GET_IDX();

   // - array get_pc_idx -
ARRAY_GET_PC_IDX();

   // - array operator= method -
   if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_OPERATOR_EQUAL();
   }

   // - array operator== method -
   if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_OPERATOR_DOUBLE_EQUAL();
   }

   // - array save_size method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_SAVE_SIZE();
   }*/

   // - array save_to method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_SAVE_TO();
   }*/

   // - array load_from method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
ARRAY_LOAD_FROM();
   }*/

   // - array print method -
//ARRAY_PRINT();

}


#define QUEUE_INIT() \
{\
printf(\
"inline void %s::init()\n"\
"{\n"\
"   size = 0;\n"\
"   used = 0;\n"\
"   begin = 0;\n"\
"   data = NULL;\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define QUEUE_INIT_SIZE() \
{\
printf(\
"inline void %s::init_size(unsigned a_size)\n"\
"{\n"\
"   init();\n"\
"   copy_resize(a_size);\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define QUEUE_CLEAR() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::clear()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::clear()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   if (data != NULL) {\n"\
);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"      %s *ptr = data;\n"\
"      %s *ptr_end = ptr + size;\n"\
"\n"\
"      do {\n"\
"	 ptr->clear();\n"\
"      } while(++ptr < ptr_end);\n"\
"\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"      cfree(data);\n"\
"   }\n"\
"\n"\
"   init();\n"\
"}\n"\
"\n"\
);\
}

#define QUEUE_FLUSH() \
{\
printf(\
"inline void %s::flush()\n"\
"{\n"\
"   copy_resize(used);\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define QUEUE_FLUAH_ALL() \
{\
   if (!(TYPE_NUMBER & c_type_flushable)) {\
printf(\
"inline void %s::flush_all()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::flush_all()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   copy_resize(used);\n"\
);\
   if (TYPE_NUMBER & c_type_flushable) {\
printf(\
"\n"\
"   if (used == 0) return;\n"\
"\n"\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + used;\n"\
"\n"\
"   do {\n"\
"      ptr->flush_all();\n"\
"   } while(++ptr < ptr_end);\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define QUEUE_SWAP() \
{\
printf(\
"inline void %s::swap(%s &second)\n"\
"{\n"\
"   unsigned tmp_unsigned = size;\n"\
"   size = second.size;\n"\
"   second.size = tmp_unsigned;\n"\
"\n"\
"   tmp_unsigned = used;\n"\
"   used = second.used;\n"\
"   second.used = tmp_unsigned;\n"\
"\n"\
"   tmp_unsigned = begin;\n"\
"   begin = second.begin;\n"\
"   second.begin = tmp_unsigned;\n"\
"\n"\
"   %s *tmp_data = data;\n"\
"   data = second.data;\n"\
"   second.data = tmp_data;\n"\
"}\n"\
"\n"\
,STRUCT_NAME,STRUCT_NAME,TYPE_NAME);\
}

#define QUEUE_INSERT() \
{\
   if (TYPE_NUMBER & c_type_basic) {\
printf(\
"inline void %s::insert(%s a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"inline void %s::insert(%s &a_value)\n"\
,STRUCT_NAME,TYPE_NAME);\
   }\
printf(\
"{\n"\
"   if (used >= size) {\n"\
"      copy_resize((size << 1) + c_array_add);\n"\
"   }\n"\
"\n"\
"   if (begin + used >= size) {\n"\
"      data[begin + used - size] = a_value;\n"\
"   }\n"\
"   else {\n"\
"      data[begin + used] = a_value;\n"\
"   }\n"\
"\n"\
"   used++;\n"\
"}\n"\
"\n"\
);\
}

#define QUEUE_INSERT_BLANK() \
{\
printf(\
"inline void %s::insert_blank()\n"\
"{\n"\
"   if (used >= size) {\n"\
"      copy_resize((size << 1) + c_array_add);\n"\
"   }\n"\
"\n"\
"   used++;\n"\
"}\n"\
"\n"\
,STRUCT_NAME);\
}

#define QUEUE_NEXT() \
{\
printf(\
"inline %s &%s::next()\n"\
"{\n"\
"   debug_assert(used > 0);\n"\
"\n"\
"   unsigned ret_idx = begin;\n"\
"\n"\
"   if (++begin >= size) {\n"\
"      begin = 0;\n"\
"   }\n"\
"\n"\
"   used--;\n"\
"   \n"\
"   return data[ret_idx];\n"\
"}\n"\
"\n"\
,TYPE_NAME,STRUCT_NAME);\
}

#define QUEUE_LAST() \
{\
printf(\
"inline %s &%s::last()\n"\
"{\n"\
"   debug_assert(used > 0);\n"\
"\n"\
"   if (begin + (used - 1) >= size) {\n"\
"      return data[begin + (used - 1) - size];\n"\
"   }\n"\
"   else {\n"\
"      return data[begin + (used - 1)];\n"\
"   }\n"\
"}\n"\
"\n"\
,TYPE_NAME,STRUCT_NAME);\
}

#define QUEUE_COPY_RESIZE() \
{\
printf(\
"void %s::copy_resize(unsigned a_size)\n"\
"{\n"\
"   debug_assert(a_size >= used);\n"\
"\n"\
"   %s *n_data;\n"\
"\n"\
"   if (a_size == 0) {\n"\
"      n_data = NULL;\n"\
"   }\n"\
"   else {\n"\
"      n_data = (%s *)cmalloc(a_size*sizeof(%s));\n"\
,STRUCT_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"\n"\
"      if (a_size > used) {\n"\
"         %s *ptr = n_data + used;\n"\
"         %s *ptr_end = n_data + a_size;\n"\
"\n"\
"         do {\n"\
"            ptr->init();\n"\
"         } while(++ptr < ptr_end);\n"\
"      }\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   }\n"\
"\n"\
"   if (used != 0) {\n"\
"      unsigned fir_cnt;\n"\
"      unsigned sec_cnt;\n"\
"\n"\
"      if (begin + used > size) {\n"\
"         sec_cnt = begin + used - size;\n"\
"         fir_cnt = used - sec_cnt;\n"\
"      }\n"\
"      else {\n"\
"         fir_cnt = used;\n"\
"         sec_cnt = 0;\n"\
"      }\n"\
"\n"\
"      memcpy(n_data,data + begin,fir_cnt*sizeof(%s));\n"\
"\n"\
"      if (sec_cnt != 0) {\n"\
"         memcpy(n_data + fir_cnt,data,sec_cnt*sizeof(%s));\n"\
"      }\n"\
"   }\n"\
"\n"\
,TYPE_NAME,TYPE_NAME);\
   if (TYPE_NUMBER & c_type_dynamic) {\
printf(\
"   if (size > used) {\n"\
"      %s *ptr;\n"\
"      %s *ptr_end;\n"\
"      %s *s_ptr;\n"\
"\n"\
"      if (begin + used >= size) {\n"\
"         ptr = data + (begin + used - size);\n"\
"         ptr_end = data + begin;\n"\
"         s_ptr = NULL;\n"\
"      }\n"\
"      else {\n"\
"         ptr = data;\n"\
"         ptr_end = data + begin;\n"\
"         s_ptr = ptr_end + used;\n"\
"      }\n"\
"\n"\
"      if (ptr < ptr_end) {\n"\
"         do {\n"\
"            ptr->clear();\n"\
"         } while(++ptr < ptr_end);\n"\
"      }\n"\
"\n"\
"      if (s_ptr != NULL) {\n"\
"         %s *s_ptr_end = data + size;\n"\
"         do {\n"\
"            s_ptr->clear();\n"\
"         } while(++s_ptr < s_ptr_end);\n"\
"      }\n"\
"   }\n"\
"\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   if (size != 0) {\n"\
"      cfree(data);\n"\
"   }\n"\
"\n"\
"   data = n_data;\n"\
"   size = a_size;\n"\
"   begin = 0;\n"\
"}\n"\
"\n"\
);\
}

#define QUEUE_OPERATOR_EQUAL() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline %s &%s::operator=(%s &src)\n"\
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);\
   }\
   else {\
printf(\
"%s &%s::operator=(%s &src)\n"\
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   clear();\n"\
"\n"\
"   if (src.used == 0) return *this;\n"\
"\n"\
"   copy_resize(src.used);\n"\
"\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   unsigned fir_cnt;\n"\
"   unsigned sec_cnt;\n"\
"\n"\
"   if (src.begin + src.used > src.size) {\n"\
"      sec_cnt = src.begin + src.used - src.size;\n"\
"      fir_cnt = src.used - sec_cnt;\n"\
"   }\n"\
"   else {\n"\
"      fir_cnt = src.used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   memcpy(data,src.data + src.begin,fir_cnt*sizeof(%s));\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      memcpy(data + fir_cnt,src.data,sec_cnt*sizeof(%s));\n"\
"   }\n"\
"\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"   unsigned sec_cnt;\n"\
"   %s *ptr = data;\n"\
"   %s *s_ptr = src.data + src.begin;\n"\
"   %s *s_ptr_end;\n"\
"\n"\
"   if (src.begin + src.used > src.size) {\n"\
"      s_ptr_end = src.data + src.size;\n"\
"      sec_cnt = src.begin + src.used - src.size;\n"\
"   }\n"\
"   else {\n"\
"      s_ptr_end = s_ptr + src.used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   do {\n"\
"      *ptr = *s_ptr; \n"\
"   } while(++ptr,++s_ptr < s_ptr_end);\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      s_ptr = src.data;\n"\
"      s_ptr_end = s_ptr + sec_cnt;\n"\
"\n"\
"      do {\n"\
"	 *ptr = *s_ptr;\n"\
"      } while(++ptr,++s_ptr < s_ptr_end);\n"\
"   }\n"\
"\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   used = src.used;\n"\
"   return *this;\n"\
"}\n"\
"\n"\
);\
}

#define QUEUE_OPERATOR_DOUBLE_EQUAL() \
{\
printf(\
"bool %s::operator==(%s &second)\n"\
"{\n"\
"   if (used != second.used) return false;\n"\
"   if (used == 0) return true;\n"\
"\n"\
,STRUCT_NAME,STRUCT_NAME);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   bool _break;\n"\
"   bool s_break;\n"\
"   unsigned pos;\n"\
"   unsigned pos_end;\n"\
"   unsigned s_pos;\n"\
"\n"\
"   _break = (begin + used > size);\n"\
"   s_break = (second.begin + second.used > second.size);\n"\
"   pos = begin;\n"\
"   s_pos = second.begin;\n"\
"\n"\
"   if (_break) {\n"\
"      pos_end = begin + used - size;\n"\
"   }\n"\
"   else {\n"\
"      pos_end = begin + used;\n"\
"   }\n"\
"\n"\
"   do {\n"\
"      if (_break) {\n"\
"	 unsigned offset = size - pos;\n"\
"	 \n"\
"	 if (s_break) {\n"\
"	    unsigned s_offset = second.size = s_pos;\n"\
"\n"\
"	    if (offset < s_offset) {\n"\
"	       if (memcmp(data + pos,second.data + s_pos,offset*sizeof(%s)) != 0) {\n"\
"		  return false;\n"\
"	       }\n"\
"\n"\
"	       s_pos += offset;\n"\
"	       pos = 0;\n"\
"	       _break = false;\n"\
"	    }\n"\
"	    else {\n"\
"	       if (memcmp(data + pos,second.data + s_pos,s_offset*sizeof(%s)) != 0) {\n"\
"		  return false;\n"\
"	       }\n"\
"\n"\
"	       if (pos += s_offset >= size) {\n"\
"		  pos = 0;\n"\
"		  _break = false;\n"\
"	       }\n"\
"	       s_pos = 0;\n"\
"	       s_break = false;\n"\
"	    }\n"\
"	 }\n"\
"	 else {\n"\
"	    if (memcmp(data + pos,second.data + s_pos,offset*sizeof(%s)) != 0) {\n"\
"	       return false;\n"\
"	    }\n"\
"	    s_pos += offset;\n"\
"	    pos = 0;\n"\
"	    _break = false;\n"\
"	 }\n"\
"      }\n"\
"      else {\n"\
"	 if (s_break) {\n"\
"	    unsigned s_offset = second.size - s_pos;\n"\
"\n"\
"	    if (memcmp(data + pos,second.data + s_pos,s_offset*sizeof(%s)) != 0) {\n"\
"	       return false;\n"\
"	    }\n"\
"	    pos += s_offset;\n"\
"	    s_pos = 0;\n"\
"	    s_break = false;\n"\
"	 }\n"\
"	 else {\n"\
"	    if (memcmp(data + pos,second.data + s_pos,(pos_end - pos)*sizeof(%s)) != 0) {\n"\
"	       return false;\n"\
"	    }\n"\
"	    else {\n"\
"	       return true;\n"\
"	    }\n"\
"	 }\n"\
"      }\n"\
"   } while(1);\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"   %s *ptr = data + begin;\n"\
"   %s *ptr_break = data + size;\n"\
"   %s *ptr_end;\n"\
"   %s *s_ptr = second.data + second.begin;\n"\
"   %s *s_ptr_break = second.data + second.size;\n"\
"\n"\
"   if (begin + used > size) {\n"\
"      ptr_end = data + (begin + used - size);\n"\
"   }\n"\
"   else {\n"\
"      ptr_end = ptr + used;\n"\
"   }\n"\
"\n"\
"   do {\n"\
"      if (!(*ptr == *s_ptr)) {\n"\
"	 return false;\n"\
"      }\n"\
"      \n"\
"      if (++ptr >= ptr_break) {\n"\
"	 ptr = data;\n"\
"      }\n"\
"\n"\
"      if (++s_ptr >= s_ptr_break) {\n"\
"	 s_ptr = second.data;\n"\
"      }\n"\
"\n"\
"   } while(ptr != ptr_end);\n"\
"\n"\
"   return true;\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define QUEUE_SAVE_SIZE() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline unsigned %s::save_size()\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"unsigned %s::save_size()\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   return sizeof(unsigned) + used*sizeof(%s);\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"   if (used == 0) return sizeof(unsigned);\n"\
"\n"\
"   unsigned ret_size = sizeof(unsigned);\n"\
"   unsigned sec_cnt;\n"\
"   %s *ptr = data + begin;\n"\
"   %s *ptr_end;\n"\
"\n"\
"   if (begin + used > size) {\n"\
"      ptr_end = data + size;\n"\
"      sec_cnt = begin + used - size;\n"\
"   }\n"\
"   else {\n"\
"      ptr_end = ptr + used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   do {\n"\
"      ret_size += ptr->save_size();\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      ptr = data;\n"\
"      ptr_end = ptr + sec_cnt;\n"\
"\n"\
"      do {\n"\
"	 ret_size += ptr->save_size();\n"\
"      } while(++ptr < ptr_end);\n"\
"   }\n"\
"\n"\
"   return ret_size;\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define QUEUE_SAVE_TO() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::save_to(char **b_ptr)\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::save_to(char **b_ptr)\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   *(unsigned *)*b_ptr = used; *b_ptr += sizeof(unsigned);\n"\
"   if (used == 0) return;\n"\
"\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   unsigned fir_cnt;\n"\
"   unsigned sec_cnt;\n"\
"\n"\
"   if (begin + used > size) {\n"\
"      sec_cnt = begin + used - size;\n"\
"      fir_cnt = used - sec_cnt;\n"\
"   }\n"\
"   else {\n"\
"      fir_cnt = used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   memcpy(*b_ptr,data + begin,fir_cnt*sizeof(%s));\n"\
"   *b_ptr += fir_cnt*sizeof(%s);\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      memcpy(*b_ptr,data,sec_cnt*sizeof(%s));\n"\
"      *b_ptr += sec_cnt*sizeof(%s);\n"\
"   }\n"\
,TYPE_NAME,TYPE_NAME,TYPE_NAME,TYPE_NAME);\
   }\
   else {\
printf(\
"   unsigned sec_cnt;\n"\
"   %s *ptr = data + begin;\n"\
"   %s *ptr_end;\n"\
"\n"\
"   if (begin + used > size) {\n"\
"      sec_cnt = begin + used - size;\n"\
"      ptr_end = data + size;\n"\
"   }\n"\
"   else {\n"\
"      ptr_end = ptr + used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   do {\n"\
"      ptr->save_to(b_ptr);\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      ptr = data;\n"\
"      ptr_end = ptr + sec_cnt;\n"\
"\n"\
"      do {\n"\
"	 ptr->save_to(b_ptr);\n"\
"      } while(++ptr < ptr_end);\n"\
"   }\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"}\n"\
"\n"\
);\
}

#define QUEUE_LOAD_FROM() \
{\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"inline void %s::load_from(char **b_ptr,char *b_ptr_end)\n"\
,STRUCT_NAME);\
   }\
   else {\
printf(\
"void %s::load_from(char **b_ptr,char *b_ptr_end)\n"\
,STRUCT_NAME);\
   }\
printf(\
"{\n"\
"   clear();\n"\
"\n"\
"   assert(*b_ptr + sizeof(unsigned) <= b_ptr_end);\n"\
"   unsigned tmp_used = *(unsigned *)*b_ptr; *b_ptr += sizeof(unsigned);\n"\
"   if (tmp_used == 0) return;\n"\
"\n"\
"   copy_resize(tmp_used);\n"\
"\n"\
);\
   if (!(TYPE_NUMBER & c_type_dynamic)) {\
printf(\
"   unsigned data_size = tmp_used*sizeof(%s);\n"\
"   assert(*b_ptr + data_size <= b_ptr_end);\n"\
"   memcpy(data,*b_ptr,data_size);\n"\
"\n"\
"   *b_ptr += data_size;\n"\
"   used = tmp_used;\n"\
,TYPE_NAME);\
   }\
   else {\
printf(\
"   %s *ptr = data;\n"\
"   %s *ptr_end = ptr + tmp_used;\n"\
"\n"\
"   do {\n"\
"      ptr->load_from(b_ptr,b_ptr_end);\n"\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   used = tmp_used;\n"\
,TYPE_NAME,TYPE_NAME);\
   }\
printf(\
"   begin = 0;\n"\
"}\n"\
"\n"\
);\
}

#define QUEUE_PRINT() \
{\
printf(\
"void %s::print()\n"\
"{\n"\
"   if (used == 0) {\n"\
"      printf(\"empty\");\n"\
"      return;\n"\
"   }\n"\
"\n"\
"   unsigned sec_cnt;\n"\
"   %s *ptr = data + begin;\n"\
"   %s *ptr_end;\n"\
"\n"\
"   if (begin + used > size) {\n"\
"      sec_cnt = begin + used - size;\n"\
"      ptr_end = data + size;\n"\
"   }\n"\
"   else {\n"\
"      ptr_end = ptr + used;\n"\
"      sec_cnt = 0;\n"\
"   }\n"\
"\n"\
"   do {\n"\
,STRUCT_NAME,TYPE_NAME,TYPE_NAME);\
   data_type_print("      ",type_idx,"(*ptr)");\
printf(\
"   } while(++ptr < ptr_end);\n"\
"\n"\
"   if (sec_cnt != 0) {\n"\
"      ptr = data;\n"\
"      ptr_end = ptr + sec_cnt;\n"\
"\n"\
"      do {\n"\
);\
   data_type_print("      ",type_idx,"(*ptr)");\
printf(\
"      } while(++ptr < ptr_end);\n"\
"   }\n"\
"}\n"\
"\n"\
);\
}

void processor_s::generate_queue_type(string_arrays_s &params)
{
   string_array_s &type_names = params[c_param_types];
   string_array_s &fun_defs = params[c_param_functions];
   string_array_s &abbs = params[c_param_names];

   assert(type_names.used == 1);

   unsigned abb_idx = abbreviations.get_idx_by_string(type_names[0].size - 1,type_names[0].data);
   assert(abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[abb_idx].number;
   data_type_s &type = data_types[type_idx];

   string_s data_type_name;
   data_type_name.init();
   data_type_name.conc_set(type.string.size - 1,type.string.data,strlen(c_cont_postfixes[c_cont_queue]),(char *)c_cont_postfixes[c_cont_queue]);

   unsigned data_type_idx;

   if ((data_type_idx = abbreviations.get_idx_by_string(data_type_name.size - 1,data_type_name.data)) == c_idx_not_exist) {
      abbreviations.push_blank();
      abbreviations.last().set(data_type_name,data_types.used);

      data_types.push_blank();
      data_type_s &data_type = data_types.last();

      data_type.cont_idx = c_cont_queue;
      data_type.string.swap(data_type_name);
      data_type.number = c_type_dynamic | c_type_flushable;
      data_type.types.push(type.string);

      data_type_idx = data_types.used - 1;
   }
   else {
      //data_type_idx = abbreviations[data_type_idx].number;
      assert(0);
   }

   data_type_name.clear();

   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
	 string_s &abb = abbs[idx];

	 assert(abbreviations.get_idx_by_string(abb.size - 1,abb.data) == c_idx_not_exist);
	 abbreviations.push_blank();
	 abbreviations.last().set(abb,data_type_idx);
      } while(++idx < abbs.used);
   }

   data_type_s &data_type = data_types[data_type_idx];

   // - definice struktury queue -

printf(
"// struct %s definition\n"
"\n"
,STRUCT_NAME);

   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
printf(
"typedef struct %s %s;\n"
,STRUCT_NAME,abbs[idx].data);
      } while(++idx < abbs.used);
printf(
"\n"
);
   }

printf(
"struct %s\n"
"{\n"
"   unsigned size;\n"
"   unsigned used;\n"
"   unsigned begin;\n"
"   %s *data;\n"
"\n"
"   inline void init();\n"
"   inline void init_size(unsigned a_size);\n"
,STRUCT_NAME,TYPE_NAME);
   if (TYPE_NUMBER & c_type_dynamic) {
printf(
"   inline void clear();\n"
);
   }
   else {
printf(
"   void clear();\n"
);
   }
printf(
"   inline void flush();\n"
);
   if (!(TYPE_NUMBER & c_type_flushable)) {
printf(
"   inline void flush_all();\n"
);
   }
   else {
printf(
"   void flush_all();\n"
);
   }
printf(
"   inline void swap(%s &second);\n"
,STRUCT_NAME);
   if (TYPE_NUMBER & c_type_basic) {
printf(
"   inline void insert(%s a_value);\n"
,TYPE_NAME);
   }
   else {
printf(
"   inline void insert(%s &a_value);\n"
,TYPE_NAME);
   }
printf(
"   inline void insert_blank();\n"
"   inline %s &next();\n"
"   inline %s &last();\n"
"   void copy_resize(unsigned a_size);\n"
,TYPE_NAME,TYPE_NAME);
   if (!(TYPE_NUMBER & c_type_dynamic)) {
printf(
"   inline %s &operator=(%s &src);\n"
,STRUCT_NAME,STRUCT_NAME);
   }
   else {
printf(
"   %s &operator=(%s &src);\n"
,STRUCT_NAME,STRUCT_NAME);
   }
printf(
"   bool operator==(%s &second);\n"
,STRUCT_NAME);
   if (!(TYPE_NUMBER & c_type_dynamic)) {
//printf(
//"   inline unsigned save_size();\n"
//"   inline void save_to(char **b_ptr);\n"
//"   inline void load_from(char **b_ptr,char *b_ptr_end);\n"
//);
   }
   else {
//printf(
//"   unsigned save_size();\n"
//"   void save_to(char **b_ptr);\n"
//"   void load_from(char **b_ptr,char *b_ptr_end);\n"
//);
   }
//printf(
//"   void print();\n"
//);
   if (fun_defs.used != 0) {
      unsigned f_idx = 0;
      do {
printf(
"   %s\n"
,fun_defs[f_idx].data);
      } while(++f_idx < fun_defs.used);
   }
printf(
"};\n"
"\n"
);
};

void processor_s::generate_queue_inlines(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   string_s &type_abb_string = data_type.types[0];
   unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
   assert(type_abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[type_abb_idx].number;
   data_type_s &type = data_types[type_idx];

   // - definice inline funkci -

printf(
"// --- struct %s inline method definition ---\n"
"\n"
,STRUCT_NAME);

   // - queue init method -
QUEUE_INIT();

   // - queue init_size method -
QUEUE_INIT_SIZE();

   // - queue clear method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
QUEUE_CLEAR();
   }

   // - queue flush method -
QUEUE_FLUSH();

   // - queue flush_all method -
   if (!(TYPE_NUMBER & c_type_flushable)) {
QUEUE_FLUAH_ALL();
   }

   // - queue swap method -
QUEUE_SWAP();

   // - queue insert method -
QUEUE_INSERT();

   // - queue insert_blank method -
QUEUE_INSERT_BLANK();

   // - queue next method -
QUEUE_NEXT();

   // - queue last method -
QUEUE_LAST();

   // - queue copy_resize method -

   // - queue operator= method -
   if (!(TYPE_NUMBER & c_type_dynamic)) {
QUEUE_OPERATOR_EQUAL();
   }

   // - queue operator== method -

   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
QUEUE_SAVE_SIZE();
   }*/

   // - queue save_to method -
   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
QUEUE_SAVE_TO();
   }*/

   // - queue load_from method -
   /*if (!(TYPE_NUMBER & c_type_dynamic)) {
QUEUE_LOAD_FROM();
   }*/

   // - queue print method -
}

void processor_s::generate_queue_methods(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   string_s &type_abb_string = data_type.types[0];
   unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
   assert(type_abb_idx != c_idx_not_exist);

   unsigned type_idx = abbreviations[type_abb_idx].number;
   data_type_s &type = data_types[type_idx];

   // - definice funkci -

printf(
"// --- struct %s method definition ---\n"
"\n"
,STRUCT_NAME);

   // - queue init method -

   // - queue init_size method -

   // - queue clear method -
   if (TYPE_NUMBER & c_type_dynamic) {
QUEUE_CLEAR();
   }

   // - queue flush method -

   // - queue flush_all method -
   if (TYPE_NUMBER & c_type_flushable) {
QUEUE_FLUAH_ALL();
   }

   // - queue swap method -

   // - queue insert method -

   // - queue insert_blank method -

   // - queue next method -

   // - queue last method -

   // - queue copy_resize method -
QUEUE_COPY_RESIZE();

   // - queue operator= method -
   if (TYPE_NUMBER & c_type_dynamic) {
QUEUE_OPERATOR_EQUAL();
   }

   // - queue operator== method -
QUEUE_OPERATOR_DOUBLE_EQUAL();

   // - queue save_size method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
QUEUE_SAVE_SIZE();
   }*/

   // - queue save_to method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
QUEUE_SAVE_TO();
   }*/

   // - queue load_from method -
   /*if (TYPE_NUMBER & c_type_dynamic) {
QUEUE_LOAD_FROM();
   }*/

   // - queue print method -
//QUEUE_PRINT();

}


#define STRUCT_INIT() \
{\
printf(\
"inline void %s::init()\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      if (TYPE_NUMBERS(t_idx) & c_type_dynamic) {\
printf(\
"   %s.init();\n"\
,VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_CLEAR() \
{\
printf(\
"inline void %s::clear()\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      if (TYPE_NUMBERS(t_idx) & c_type_dynamic) {\
printf(\
"   %s.clear();\n"\
,VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_SET() \
{\
printf(\
"inline void %s::set("\
,STRUCT_NAME);\
   if (TYPE_NUMBERS(0) & c_type_basic) {\
printf(\
"%s a_%s"\
,TYPE_NAMES(0),VAR_NAMES(0));\
   }\
   else {\
printf(\
"%s &a_%s"\
,TYPE_NAMES(0),VAR_NAMES(0));\
   }\
   if (TYPE_CNT > 1) {\
      unsigned t_idx = 1;\
      do {\
	 if (TYPE_NUMBERS(t_idx) & c_type_basic) {\
printf(\
",%s a_%s"\
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx));\
	 }\
	 else {\
printf(\
",%s &a_%s"\
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx));\
	 }\
      } while(++t_idx < TYPE_CNT);\
   }\
printf(\
")\n"\
"{\n"\
);\
   t_idx = 0;\
   do {\
printf(\
"   %s = a_%s;\n"\
,VAR_NAMES(t_idx),VAR_NAMES(t_idx));\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_FLUSH_ALL() \
{\
printf(\
"inline void %s::flush_all()\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      if (TYPE_NUMBERS(t_idx) & c_type_flushable) {\
printf(\
"   %s.flush_all();\n"\
,VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_SWAP() \
{\
printf(\
"inline void %s::swap(%s &second)\n"\
"{"\
,STRUCT_NAME,STRUCT_NAME);\
   t_idx = 0;\
   do {\
printf(\
"\n"\
);\
      if (TYPE_NUMBERS(t_idx) & c_type_basic) {\
printf(\
"   %s tmp_%s = %s;\n"\
"   %s = second.%s;\n"\
"   second.%s = tmp_%s;\n"\
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx),VAR_NAMES(t_idx),VAR_NAMES(t_idx),VAR_NAMES(t_idx),VAR_NAMES(t_idx),VAR_NAMES(t_idx));\
      }\
      else {\
printf(\
"   %s.swap(second.%s);\n"\
,VAR_NAMES(t_idx),VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_OPERATOR_EQUAL() \
{\
printf(\
"inline %s &%s::operator=(%s &src)\n"\
"{\n"\
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);\
   t_idx = 0;\
   do {\
printf(\
"   %s = src.%s;\n"\
,VAR_NAMES(t_idx),VAR_NAMES(t_idx));\
   } while(++t_idx < TYPE_CNT);\
printf(\
"\n"\
"   return *this;\n"\
"}\n"\
"\n"\
);\
}

#define STRUCT_OPERATOR_DOUBLE_EQUAL() \
{\
printf(\
"inline bool %s::operator==(%s &second)\n"\
"{\n"\
"   return (%s == second.%s"\
,STRUCT_NAME,STRUCT_NAME,VAR_NAMES(0),VAR_NAMES(0));\
   if (TYPE_CNT > 1) {\
      t_idx = 1;\
      do {\
printf(\
" && %s == second.%s"\
,VAR_NAMES(t_idx),VAR_NAMES(t_idx));\
      } while(++t_idx < TYPE_CNT);\
   }\
printf(\
");\n"\
"}\n"\
"\n"\
);\
}

#define STRUCT_PART_COMPARE() \
{\
   if (data_type.number & c_type_part_comparable) {\
printf(\
"inline bool %s::part_compare(%s &second)\n"\
"{\n"\
"   return (%s == second.%s"\
,STRUCT_NAME,STRUCT_NAME,VAR_NAMES(COMP_IDXS(0)),VAR_NAMES(COMP_IDXS(0)));\
      if (COMP_IDX_CNT > 1) {\
	 t_idx = 1;\
	 do {\
printf(\
" && %s == second.%s"\
,VAR_NAMES(COMP_IDXS(t_idx)),VAR_NAMES(COMP_IDXS(t_idx)));\
	 } while(++t_idx < COMP_IDX_CNT);\
      }\
printf(\
");\n"\
"}\n"\
"\n"\
);\
   }\
}

#define STRUCT_SAVE_SIZE() \
{\
printf(\
"inline unsigned %s::save_size()\n"\
"{\n"\
"   return ("\
,STRUCT_NAME);\
   if (!(TYPE_NUMBERS(0) & c_type_dynamic)) {\
printf(\
"sizeof(%s)"\
,TYPE_NAMES(0));\
   }\
   else {\
printf(\
"%s.save_size()"\
,VAR_NAMES(0));\
   }\
   if (TYPE_CNT > 1) {\
      t_idx = 1;\
      do {\
	 if (!(TYPE_NUMBERS(t_idx) & c_type_dynamic)) {\
printf(\
" + sizeof(%s)"\
,TYPE_NAMES(t_idx));\
	 }\
	 else {\
printf(\
" + %s.save_size()"\
,VAR_NAMES(t_idx));\
	 }\
      } while(++t_idx < TYPE_CNT);\
   }\
printf(\
");\n"\
"}\n"\
"\n"\
);\
}

#define STRUCT_SAVE_TO() \
{\
printf(\
"inline void %s::save_to(char **b_ptr)\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      if (TYPE_NUMBERS(t_idx) & c_type_basic) {\
printf(\
"   *(%s *)*b_ptr = %s; *b_ptr += sizeof(%s);\n"\
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx),TYPE_NAMES(t_idx));\
      }\
      else {\
printf(\
"   %s.save_to(b_ptr);\n"\
,VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_LOAD_FROM() \
{\
printf(\
"inline void %s::load_from(char **b_ptr,char *b_ptr_end)\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      if (TYPE_NUMBERS(t_idx) & c_type_basic) {\
printf(\
"   assert(*b_ptr + sizeof(%s) <= b_ptr_end);\n"\
"   %s = *(%s *)b_ptr; *b_ptr += sizeof(%s);\n"\
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx),TYPE_NAMES(t_idx),TYPE_NAMES(t_idx));\
      }\
      else {\
printf(\
"   %s.load_from(b_ptr,b_ptr_end);\n"\
,VAR_NAMES(t_idx));\
      }\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

#define STRUCT_PRINT() \
{\
printf(\
"inline void %s::print()\n"\
"{\n"\
,STRUCT_NAME);\
   t_idx = 0;\
   do {\
      data_type_print("   ",type_idxs[t_idx],VAR_NAMES(t_idx));\
   } while(++t_idx < TYPE_CNT);\
printf(\
"}\n"\
"\n"\
);\
}

void processor_s::generate_struct_type(string_arrays_s &params)
{
   string_array_s &type_names = params[c_param_types];
   string_array_s &vars = params[c_param_variables];
   string_array_s &comp_idx_strings = params[c_param_compare];
   string_array_s &fun_defs = params[c_param_functions];
   string_array_s &abbs = params[c_param_names];

   assert(type_names.used >= 1 && type_names.used == vars.used);

   unsigned type_cnt = type_names.used;
   unsigned type_idxs[type_cnt];
   data_type_s *types[type_cnt];

   {
      unsigned tn_idx = 0;
      do {
	 unsigned abb_idx = abbreviations.get_idx_by_string(type_names[tn_idx].size - 1,type_names[tn_idx].data);
	 assert(abb_idx != c_idx_not_exist);
	 
	 unsigned type_idx = abbreviations[abb_idx].number;
	 type_idxs[tn_idx] = type_idx;
	 types[tn_idx] = &data_types[type_idx];
      } while(++tn_idx < type_cnt);
   }

   // vypocet velikosti jmena typu

   unsigned data_type_name_len = 0;
   {
      unsigned t_idx = 0;
      do {
	 data_type_name_len += types[t_idx]->string.size;
      } while(++t_idx < type_cnt);

      data_type_name_len += strlen(c_cont_postfixes[c_cont_struct]) - 1;
   }

   // slozeni jmena typu
   string_s data_type_name;
   data_type_name.init();
   data_type_name.create(data_type_name_len);

   {
      unsigned t_idx = 0;
      char *dtn_ptr = data_type_name.data;
      do {
	 data_type_s &type = *types[t_idx];
	 memcpy(dtn_ptr,type.string.data,type.string.size - 1);
	 dtn_ptr += type.string.size - 1;
	 *dtn_ptr++ = '_';
      } while(++t_idx < type_cnt);

      memcpy(--dtn_ptr,c_cont_postfixes[c_cont_struct],strlen(c_cont_postfixes[c_cont_struct]));
   }

   // prevedeni indexu porovnatelnych promennych na celocidelnou reprezentaci
   unsigned comp_idx_cnt = comp_idx_strings.used;
   unsigned comp_idxs[comp_idx_cnt];
   
   if (comp_idx_cnt != 0) {
      unsigned c_idx = 0;
      do {
	 unsigned comp_idx = atoi(comp_idx_strings[c_idx].data);
	 assert(comp_idx < type_cnt)
	 comp_idxs[c_idx] = comp_idx;
      } while(++c_idx < comp_idx_cnt);
   }


   unsigned data_type_idx;

   // pripadne vytvoreni zkratky a noveho datoveho typu
   if ((data_type_idx = abbreviations.get_idx_by_string(data_type_name.size - 1,data_type_name.data)) == c_idx_not_exist) {
      abbreviations.push_blank();
      abbreviations.last().set(data_type_name,data_types.used);

      data_types.push_blank();
      data_type_s &data_type = data_types.last();

      data_type.cont_idx = c_cont_struct;
      data_type.string.swap(data_type_name);

      bool dynamic = false;
      bool flushable = false;

      data_type_s **t_pptr = types;
      data_type_s **t_pptr_end = types + type_cnt;
      do {
	 if ((*t_pptr)->number & c_type_dynamic) {
	    dynamic = true;
	    break;
	 }
      } while(++t_pptr < t_pptr_end);

      t_pptr = types;
      do {
	 if ((*t_pptr)->number & c_type_flushable) {
	    flushable = true;
	    break;
	 }
      } while(++t_pptr < t_pptr_end);

      data_type.number = (c_type_static << dynamic) | (flushable << 3) | (comp_idx_strings.used != 0) << 4;

      {
	 string_array_s &dt_type_names = data_type.types;
	 data_type_s **t_pptr = types;
	 data_type_s **t_pptr_end = types + type_cnt;

	 do {
	    dt_type_names.push((*t_pptr)->string);
	 } while(++t_pptr < t_pptr_end);
      }
      
      data_type.vars.swap(vars);
      data_type.compare_idxs.set(comp_idx_cnt,comp_idxs);

      data_type_idx = data_types.used - 1;
   }
   else {
      //data_type_idx = abbreviations[data_type_idx].number;
      assert(0);
   }

   data_type_name.clear();

   // zkontrolovani a zapsani zkratek
   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
	 string_s &abb = abbs[idx];

	 assert(abbreviations.get_idx_by_string(abb.size - 1,abb.data) == c_idx_not_exist);
	 abbreviations.push_blank();
	 abbreviations.last().set(abb,data_type_idx);
      } while(++idx < abbs.used);
   }

   data_type_s &data_type = data_types[data_type_idx];

   // - definice struktury struct -

printf(
"// structure %s definition\n"
"\n"
,STRUCT_NAME);

   if (abbs.used != 0) {
      unsigned idx = 0;
      do {
printf(
"typedef struct %s %s;\n"
,STRUCT_NAME,abbs[idx].data);
      } while(++idx < abbs.used);
printf(
"\n"
);
   }

printf(
"struct %s\n"
"{\n"
,STRUCT_NAME);
   unsigned t_idx = 0;
   do {
printf(
"   %s %s;\n"
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx));
   } while(++t_idx < TYPE_CNT);
printf(
"\n"
"   inline void init();\n"
"   inline void clear();\n"
"   inline void set("
);
   if (TYPE_NUMBERS(0) & c_type_basic) {
printf(
"%s a_%s"
,TYPE_NAMES(0),VAR_NAMES(0));
   }
   else {
printf(
"%s &a_%s"
,TYPE_NAMES(0),VAR_NAMES(0));
   }
   if (TYPE_CNT > 1) {
      unsigned t_idx = 1;
      do {
	 if (TYPE_NUMBERS(t_idx) & c_type_basic) {
printf(
",%s a_%s"
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx));
	 }
	 else {
printf(
",%s &a_%s"
,TYPE_NAMES(t_idx),VAR_NAMES(t_idx));
	 }
      } while(++t_idx < TYPE_CNT);
   }
printf(
");\n"
"   inline void flush_all();\n"
"   inline void swap(%s &second);\n"
"   inline %s &operator=(%s &src);\n"
"   inline bool operator==(%s &second);\n"
,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME,STRUCT_NAME);
   if (data_type.number & c_type_part_comparable) {
printf(
"   inline bool part_compare(%s &second);\n"
,STRUCT_NAME);
   }
//printf(
//"   inline unsigned save_size();\n"
//"   inline void save_to(char **b_ptr);\n"
//"   inline void load_from(char **b_ptr,char *b_ptr_end);\n"
//"   inline void print();\n"
//);
   if (fun_defs.used != 0) {
      unsigned f_idx = 0;
      do {
printf(
"   %s\n"
,fun_defs[f_idx].data);
      } while(++f_idx < fun_defs.used);
   }
printf(
"};\n"
"\n"
);
};

void processor_s::generate_struct_inlines(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   unsigned type_cnt = data_type.types.used;
   unsigned type_idxs[type_cnt];
   data_type_s *types[type_cnt];

   {
      unsigned tn_idx = 0;
      do {
	 string_s &type_abb_string = data_type.types[tn_idx];
	 unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
	 assert(type_abb_idx != c_idx_not_exist);

	 type_idxs[tn_idx] = abbreviations[type_abb_idx].number;
	 types[tn_idx] = &data_types[type_idxs[tn_idx]];
	 
      } while(++tn_idx < type_cnt);
   }

   unsigned t_idx;

   // - definice inline fuknci -

printf(
"// --- struct %s inline method definition ---\n"
"\n"
,STRUCT_NAME);

   // - struct init method -
STRUCT_INIT();

   // - struct clear method -
STRUCT_CLEAR();

   // - struct set method -
STRUCT_SET();

   // - struct flush_all method  -
STRUCT_FLUSH_ALL();

   // - struct swap method -
STRUCT_SWAP();

   // - struct operator= method -
STRUCT_OPERATOR_EQUAL();

   // - struct operator== method -
STRUCT_OPERATOR_DOUBLE_EQUAL();

   // - struct part_compare method -
STRUCT_PART_COMPARE();

   // - struct save_size method -
//STRUCT_SAVE_SIZE();

   // - struct save_to method -
//STRUCT_SAVE_TO();

   // - struct load_from method -
//STRUCT_LOAD_FROM();

   // - struct print method -
//STRUCT_PRINT();

}

void processor_s::generate_struct_methods(unsigned a_dt_idx)
{
   data_type_s &data_type = data_types[a_dt_idx];
   
   unsigned type_cnt = data_type.types.used;
   unsigned type_idxs[type_cnt];
   data_type_s *types[type_cnt];

   {
      unsigned tn_idx = 0;
      do {
	 string_s &type_abb_string = data_type.types[tn_idx];
	 unsigned type_abb_idx = abbreviations.get_idx_by_string(type_abb_string.size - 1,type_abb_string.data);
	 assert(type_abb_idx != c_idx_not_exist);

	 type_idxs[tn_idx] = abbreviations[type_abb_idx].number;
	 types[tn_idx] = &data_types[type_idxs[tn_idx]];
	 
      } while(++tn_idx < type_cnt);
   }

   // - definice fuknci -

printf(
"// --- struct %s method definition ---\n"
"\n"
,STRUCT_NAME);

   // - struct init method -

   // - struct clear method -

   // - struct set method -

   // - struct flush_all method  -

   // - struct swap method -

   // - struct operator= method -

   // - struct operator== method -

   // - struct part_compare method -

   // - struct save_size method -

   // - struct save_to method -

   // - struct load_from method -

   // - struct print method -
}


void processor_s::generate_container_def(string_s &cont_name,string_arrays_s &cont_params)
{
   unsigned idx = 0;
   do {
      if (cont_name.compare_char_ptr(strlen(c_cont_names[idx]),(char *)c_cont_names[idx])) {
	 break;
      }
   } while(++idx < c_cont_cnt);

   switch (idx) {
   case c_cont_array:
      generate_array_type(cont_params);
      break;
   case c_cont_queue:
      generate_queue_type(cont_params);
      break;
   case c_cont_struct:
      generate_struct_type(cont_params);
      break;
   default:
      assert(0);
   }
}

void processor_s::generate_type_inlines(unsigned a_length,char *a_data)
{
   unsigned abb_idx = abbreviations.get_idx_by_string(a_length,a_data);
   assert(abb_idx != c_idx_not_exist);

   unsigned data_type_idx = abbreviations[abb_idx].number;

   switch (data_types[data_type_idx].cont_idx) {
   case c_cont_array:
      generate_array_inlines(data_type_idx);
      break;
   case c_cont_queue:
      generate_queue_inlines(data_type_idx);
      break;
   case c_cont_struct:
      generate_struct_inlines(data_type_idx);
      break;
   default:
      assert(0);
   }
}

void processor_s::generate_type_methods(unsigned a_length,char *a_data)
{
   unsigned abb_idx = abbreviations.get_idx_by_string(a_length,a_data);
   assert(abb_idx != c_idx_not_exist);

   unsigned data_type_idx = abbreviations[abb_idx].number;

   switch (data_types[data_type_idx].cont_idx) {
   case c_cont_array:
      generate_array_methods(data_type_idx);
      break;
   case c_cont_queue:
      generate_queue_methods(data_type_idx);
      break;
   case c_cont_struct:
      generate_struct_methods(data_type_idx);
      break;
   default:
      assert(0);
   }
}

void processor_s::init_processor()
{
   clear();

   /*
    * nastaveni zakladnich datovych typu
    */
   {
      unsigned idx = 0;
      do {
	 data_types.push_blank();
	 data_type_s &data_type = data_types.last();

	 const char *c_basic_type = c_basic_types[idx];
	 data_type.string.set(strlen(c_basic_type),(char *)c_basic_type);
	 data_type.number = c_basic_type_types[idx];
      } while(++idx < c_basic_type_cnt);
   }

   /*
    * nastaveni zakladnich zkratek
    */
   {
      unsigned idx = 0;
      do {
	 abbreviations.push_blank();
	 abbreviation_s &abbreviation = abbreviations.last();

	 const char *c_basic_abbreviation = c_basic_abbreviations[idx];
	 abbreviation.string.set(strlen(c_basic_abbreviation),(char *)c_basic_abbreviation);
	 abbreviation.number = c_basic_abbreviation_types[idx];
      } while(++idx < c_basic_abbreviation_cnt);
   }
}

void processor_s::run(char *file_name)
{

   /*
    * zapis zakladnich definici
    */

printf(
"\n"
"typedef bool bb;\n"
"typedef char bc;\n"
"typedef unsigned char uc;\n"
"typedef short int si;\n"
"typedef unsigned short int usi;\n"
"typedef int bi;\n"
"typedef unsigned int ui;\n"
"typedef long int li;\n"
"typedef unsigned long uli;\n"
"typedef long long int lli;\n"
"typedef unsigned long long int ulli;\n"
"typedef float bf;\n"
"typedef double bd;\n"
"typedef long double ld;\n"
"\n"
);

   process_s process;
   process.init();

   process.processor_ptr = (unsigned)this;
   process.run_on(file_name);

   process.clear();

   //data_types.print();
   //abbreviations.print();
}

void processor_s::save_data(char *file_name)
{
   assert(file_name != NULL);

   unsigned save_size = data_types.save_size() + abbreviations.save_size();
   
   char *buffer = (char *)cmalloc(save_size);
   char *b_ptr = buffer;

   data_types.save_to(&b_ptr);
   abbreviations.save_to(&b_ptr);

   assert((unsigned)(b_ptr - buffer) == save_size);
   
   FILE *f = fopen(file_name,"wb");
   assert(f != NULL);
   fwrite(buffer,save_size,1,f);
   fclose(f);

   cfree(buffer);
}

void processor_s::load_and_merge_data(char *file_name)
{
   assert(file_name != NULL);

   data_types_s f_data_types;
   f_data_types.init();

   abbreviations_s f_abbreviations;
   f_abbreviations.init();

   FILE *f = fopen(file_name,"rb");
   assert(f != NULL);

   fseek(f,0,SEEK_END);
   unsigned file_size = ftell(f);
   fseek(f,0,SEEK_SET);

   char *buffer = (char *)cmalloc(file_size);

   fread(buffer,file_size,1,f);
   fclose(f);

   char *b_ptr = buffer;

   f_abbreviations.clear();
   f_data_types.clear();

   f_data_types.load_from(&b_ptr);
   f_abbreviations.load_from(&b_ptr);
   assert((unsigned)(b_ptr - buffer) == file_size);

   cfree(buffer);

   // - merge -
   {
      abbreviation_s *a_ptr = f_abbreviations.data;
      abbreviation_s *a_ptr_end = a_ptr + f_abbreviations.used;

      do {
	 unsigned idx = abbreviations.get_idx_by_string(a_ptr->string.size - 1,a_ptr->string.data);

	 if (idx != c_idx_not_exist) {
	    assert(data_types[abbreviations[idx].number] == f_data_types[a_ptr->number]);
	 }
	 else {
	    data_type_s &f_data_type = f_data_types[a_ptr->number];

	    unsigned d_idx = data_types.get_idx(f_data_type);

	    if (d_idx != c_idx_not_exist) {
	       abbreviations.push_blank();
	       abbreviations.last().swap(*a_ptr);
	       abbreviations.last().number = d_idx;
	    }
	    else {
	       data_types.push(f_data_type);
	       abbreviations.push_blank();
	       abbreviations.last().swap(*a_ptr);
	       abbreviations.last().number = data_types.used - 1;
	    }
	 }
      } while(++a_ptr < a_ptr_end);
   }

   f_abbreviations.clear();
   f_data_types.clear();
}




/*
 * identifikace operaci prirazenych k redukcim
 */

enum {
   c_reduce_null_0 = 0,
   c_reduce_null_1,
   c_reduce_null_2,
   c_reduce_header,
   c_reduce_include,
   c_reduce_inlines,
   c_reduce_methods,
   c_reduce_gen_container,
   c_reduce_null_3,
   c_reduce_null_4,
   c_reduce_null_5,
   c_reduce_set_types,
   c_reduce_set_variables,
   c_reduce_set_compare,
   c_reduce_element_second,
   c_reduce_element_first,
   c_reduce_function,
   c_reduce_name,
};

/*
 * rozkladove konstanty
 */

const unsigned short c_escape_char = 256;
const unsigned c_rule_cnt = 18;
const unsigned rule_head_idxs[c_rule_cnt] = {16, 17, 17, 18, 18, 18, 18, 18, 19, 19, 20, 21, 21, 21, 22, 22, 20, 20, };
const unsigned rule_body_lengths[c_rule_cnt] = {4, 2, 1, 3, 3, 3, 3, 3, 2, 1, 3, 1, 1, 1, 2, 1, 1, 1, };

/*
 * rozkladova tabulka
 */

#define blank c_idx_not_exist
#define SHIFT(VALUE) VALUE
#define REDUCE(VALUE) c_lalr_table_reduce_base + VALUE
#define GOTO(VALUE) VALUE

const unsigned c_lalr_table_reduce_base = 0x80000000;
const unsigned c_terminal_plus_nonterminal_cnt = 23;
const unsigned lalr_state_cnt = 34;

const unsigned lalr_table[lalr_state_cnt*c_terminal_plus_nonterminal_cnt] = {
    SHIFT(1),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,    SHIFT(4),    SHIFT(5),    SHIFT(6),    SHIFT(7),    SHIFT(8),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,     GOTO(2),     GOTO(3),       blank,       blank,       blank,       blank,
       blank,   SHIFT(10),    SHIFT(4),    SHIFT(5),    SHIFT(6),    SHIFT(7),    SHIFT(8),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,     GOTO(9),       blank,       blank,       blank,       blank,
       blank,   REDUCE(2),   REDUCE(2),   REDUCE(2),   REDUCE(2),   REDUCE(2),   REDUCE(2),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(11),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(12),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(13),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(14),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(19),   SHIFT(18),   SHIFT(20),   SHIFT(21),   SHIFT(22),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,    GOTO(15),    GOTO(16),    GOTO(17),       blank,
       blank,   REDUCE(1),   REDUCE(1),   REDUCE(1),   REDUCE(1),   REDUCE(1),   REDUCE(1),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(23),       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(24),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(25),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(26),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(27),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(19),   SHIFT(18),   SHIFT(20),   SHIFT(21),   SHIFT(22),       blank,   SHIFT(29),       blank,       blank,       blank,       blank,       blank,       blank,       blank,    GOTO(28),    GOTO(17),       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   REDUCE(9),   REDUCE(9),   REDUCE(9),   REDUCE(9),   REDUCE(9),       blank,   REDUCE(9),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(31),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,    GOTO(30),
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(16),  REDUCE(16),  REDUCE(16),  REDUCE(16),  REDUCE(16),       blank,  REDUCE(16),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(17),  REDUCE(17),  REDUCE(17),  REDUCE(17),  REDUCE(17),       blank,  REDUCE(17),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(11),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(12),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(13),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,   REDUCE(3),   REDUCE(3),   REDUCE(3),   REDUCE(3),   REDUCE(3),   REDUCE(3),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,   REDUCE(4),   REDUCE(4),   REDUCE(4),   REDUCE(4),   REDUCE(4),   REDUCE(4),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,   REDUCE(5),   REDUCE(5),   REDUCE(5),   REDUCE(5),   REDUCE(5),   REDUCE(5),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,   REDUCE(6),   REDUCE(6),   REDUCE(6),   REDUCE(6),   REDUCE(6),   REDUCE(6),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   REDUCE(8),   REDUCE(8),   REDUCE(8),   REDUCE(8),   REDUCE(8),       blank,   REDUCE(8),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,   REDUCE(7),   REDUCE(7),   REDUCE(7),   REDUCE(7),   REDUCE(7),   REDUCE(7),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,   SHIFT(32),       blank,       blank,       blank,       blank,   SHIFT(33),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(15),       blank,       blank,       blank,       blank,  REDUCE(15),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(14),       blank,       blank,       blank,       blank,  REDUCE(14),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
       blank,       blank,       blank,       blank,       blank,       blank,  REDUCE(10),  REDUCE(10),  REDUCE(10),  REDUCE(10),  REDUCE(10),       blank,  REDUCE(10),       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,       blank,
};

/*
 * funkce struktury lalr_stack_s
 */

inline void lalr_stack_s::push(unsigned a_first_num)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   lalr_stack_element_s &target = data[used++];

   target.first_num = a_first_num;
}

inline void lalr_stack_s::push(unsigned a_first_num,unsigned a_second_num,unsigned a_third_num)
{
   if (used >= size) {
      copy_resize(size + c_array_add);
   }

   lalr_stack_element_s &target = data[used++];

   target.first_num = a_first_num;
   target.second_num = a_second_num;
   target.third_num = a_third_num;
}

/*
 * funkce struktury process_s
 */

unsigned process_s::final_automata_recognize(string_s &source_string,unsigned &input_idx,unsigned &line_cnt)
{

   unsigned source_string_length = source_string.size - 1;

#define GET_NEXT_CHAR() \
{\
   if (input_idx < source_string_length) {\
      in_char = source_string[input_idx];\
\
      if (in_char == '\\') {\
         assert(input_idx + 1 < source_string_length);\
         in_char = c_escape_char;\
      }\
   }\
   else {\
      in_char = '\0';\
   }\
}

#define CLOSE_CHAR(RET_TERM_IDX) \
{\
   if (in_char == '\0') {\
      return RET_TERM_IDX;\
   }\
\
   if (in_char == '\n') {\
      line_cnt++;\
   }\
\
   if (in_char == c_escape_char) {\
      input_idx += 2;\
   }\
   else {\
      input_idx++;\
   }\
}

   unsigned short in_char;

// - STAV 0 - 
   GET_NEXT_CHAR();

   if (in_char == 0)
      goto state_1_label;

   if (in_char == '"')
      goto state_2_label;

   if (in_char == '$')
      goto state_3_label;

   if (in_char == ';')
      goto state_4_label;

   if (in_char == '<')
      goto state_5_label;

   if (in_char == '>')
      goto state_6_label;

   if (in_char == '@')
      goto state_7_label;

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'h')
      goto state_9_label;

   if (in_char == 'i')
      goto state_10_label;

   if (in_char == 'm')
      goto state_11_label;

   if (in_char == ' ' || in_char == '\t' || in_char == '\n')
      goto state_12_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 1 - 
state_1_label:
   CLOSE_CHAR(15)
   return 15;

// - STAV 2 - 
state_2_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == '"')
      goto state_13_label;

   if (in_char != 34)
      goto state_2_label;

   return c_idx_not_exist;

// - STAV 3 - 
state_3_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 10)
      goto state_14_label;

   if (in_char != 10)
      goto state_3_label;

   return c_idx_not_exist;

// - STAV 4 - 
state_4_label:
   CLOSE_CHAR(12)
   return 12;

// - STAV 5 - 
state_5_label:
   CLOSE_CHAR(8)
   GET_NEXT_CHAR();

   if (in_char == '-')
      goto state_15_label;

   return 8;

// - STAV 6 - 
state_6_label:
   CLOSE_CHAR(11)
   return 11;

// - STAV 7 - 
state_7_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'b')
      goto state_16_label;

   if (in_char == 'e')
      goto state_17_label;

   return c_idx_not_exist;

// - STAV 8 - 
state_8_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 9 - 
state_9_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'e')
      goto state_18_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 10 - 
state_10_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'n')
      goto state_19_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 11 - 
state_11_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'e')
      goto state_20_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 12 - 
state_12_label:
   CLOSE_CHAR(13)
   GET_NEXT_CHAR();

   if (in_char == ' ' || in_char == '\t' || in_char == '\n')
      goto state_12_label;

   return 13;

// - STAV 13 - 
state_13_label:
   CLOSE_CHAR(7)
   return 7;

// - STAV 14 - 
state_14_label:
   CLOSE_CHAR(14)
   return 14;

// - STAV 15 - 
state_15_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'c')
      goto state_21_label;

   if (in_char == 'v')
      goto state_22_label;

   return c_idx_not_exist;

// - STAV 16 - 
state_16_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'e')
      goto state_23_label;

   return c_idx_not_exist;

// - STAV 17 - 
state_17_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'n')
      goto state_24_label;

   return c_idx_not_exist;

// - STAV 18 - 
state_18_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'a')
      goto state_25_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 19 - 
state_19_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'c')
      goto state_26_label;

   if (in_char == 'l')
      goto state_27_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 20 - 
state_20_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 't')
      goto state_28_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 21 - 
state_21_label:
   CLOSE_CHAR(10)
   return 10;

// - STAV 22 - 
state_22_label:
   CLOSE_CHAR(9)
   return 9;

// - STAV 23 - 
state_23_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'g')
      goto state_29_label;

   return c_idx_not_exist;

// - STAV 24 - 
state_24_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'd')
      goto state_30_label;

   return c_idx_not_exist;

// - STAV 25 - 
state_25_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'd')
      goto state_31_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 26 - 
state_26_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'l')
      goto state_32_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 27 - 
state_27_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'i')
      goto state_33_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 28 - 
state_28_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'h')
      goto state_34_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 29 - 
state_29_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'i')
      goto state_35_label;

   return c_idx_not_exist;

// - STAV 30 - 
state_30_label:
   CLOSE_CHAR(1)
   return 1;

// - STAV 31 - 
state_31_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'e')
      goto state_36_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 32 - 
state_32_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'u')
      goto state_37_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 33 - 
state_33_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'n')
      goto state_38_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 34 - 
state_34_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'o')
      goto state_39_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 35 - 
state_35_label:
   CLOSE_CHAR(c_idx_not_exist)
   GET_NEXT_CHAR();

   if (in_char == 'n')
      goto state_40_label;

   return c_idx_not_exist;

// - STAV 36 - 
state_36_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'r')
      goto state_41_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 37 - 
state_37_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'd')
      goto state_42_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 38 - 
state_38_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'e')
      goto state_43_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 39 - 
state_39_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'd')
      goto state_44_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 40 - 
state_40_label:
   CLOSE_CHAR(0)
   return 0;

// - STAV 41 - 
state_41_label:
   CLOSE_CHAR(2)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 2;

// - STAV 42 - 
state_42_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 'e')
      goto state_45_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 43 - 
state_43_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 's')
      goto state_46_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 44 - 
state_44_label:
   CLOSE_CHAR(6)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char == 's')
      goto state_47_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 6;

// - STAV 45 - 
state_45_label:
   CLOSE_CHAR(3)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 3;

// - STAV 46 - 
state_46_label:
   CLOSE_CHAR(4)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 4;

// - STAV 47 - 
state_47_label:
   CLOSE_CHAR(5)
   GET_NEXT_CHAR();

   if (in_char == '_')
      goto state_8_label;

   if (in_char >= '0' && in_char <= '9')
      goto state_8_label;

   if ((in_char >= 'a' && in_char <= 'z') || (in_char >= 'A' && in_char <= 'Z'))
      goto state_8_label;

   return 5;

}

void process_s::parse_def_code(string_s &def_code)
{
   lalr_stack.used = 0;
   lalr_stack.push(0);

   unsigned old_input_idx = 0;
   unsigned input_idx = 0;
   unsigned line_cnt = 1;
   unsigned ret_term = c_idx_not_exist;
   unsigned type_var_trigger = 0;

   do {

      while (ret_term == c_idx_not_exist) {
         old_input_idx = input_idx;

         ret_term = final_automata_recognize(def_code,input_idx,line_cnt);
         assert(ret_term != c_idx_not_exist);

         if (ret_term == 13 || ret_term == 14) {
            ret_term = c_idx_not_exist;
         }
      }

      // - nalezeni akce v tabulce akci -
      unsigned parse_action = lalr_table[lalr_stack.last().first_num*c_terminal_plus_nonterminal_cnt + ret_term];
      assert(parse_action != c_idx_not_exist);

      // - akce SHIFT -
      if (parse_action < c_lalr_table_reduce_base) {

         if (ret_term == 15) {
            break;
         }

         // - vlozi na zasobnik novy stav a pozici terminalu ve zdrojovem retezci -
         lalr_stack.push(parse_action,old_input_idx,input_idx);
         ret_term = c_idx_not_exist;
      }

      // -akce REDUCE-
      else {
         parse_action -= c_lalr_table_reduce_base;

         // - reakce na redukci podle pravidla -
	 switch (parse_action) {
	 case c_reduce_header: // oznaceni hlavickoveho souboru
	    {
	       lalr_stack_element_s &lse = lalr_stack[lalr_stack.used - 2];

	       unsigned tmp_char_idx = lse.third_num - 1;
	       char tmp_char = def_code.data[tmp_char_idx];
	       def_code.data[tmp_char_idx] = '\0';

	       char dta_file_name[256];
	       unsigned dta_file_name_length = snprintf(dta_file_name,256,"%s.dta",def_code.data + lse.second_num + 1);
	       assert(dta_file_name_length < 256);

	       def_code.data[tmp_char_idx] = tmp_char;
	       
	       ((processor_s *)processor_ptr)->load_and_merge_data(dta_file_name);
	    }
	    break;
	 case c_reduce_include: //otevreni dalsiho zdroje
	    {
	       lalr_stack_element_s &lse = lalr_stack[lalr_stack.used - 2];

	       unsigned tmp_char_idx = lse.third_num - 1;
	       char tmp_char = def_code.data[tmp_char_idx];
	       def_code.data[tmp_char_idx] = '\0';

	       process_s process;
	       process.init();

	       process.processor_ptr = processor_ptr;
	       process.run_on(def_code.data + lse.second_num + 1);
	       process.clear();

	       def_code.data[tmp_char_idx] = tmp_char;
	    }
	    break;
	 case c_reduce_inlines:
	    {
	       lalr_stack_element_s &lse = lalr_stack[lalr_stack.used - 2];
	       
	       ((processor_s *)processor_ptr)->generate_type_inlines(lse.third_num - lse.second_num - 2,def_code.data + lse.second_num + 1);
	    }
	    break;
	 case c_reduce_methods:
	    {
	       lalr_stack_element_s &lse = lalr_stack[lalr_stack.used - 2];
	       
	       ((processor_s *)processor_ptr)->generate_type_methods(lse.third_num - lse.second_num - 2,def_code.data + lse.second_num + 1);
	    }
	    break;
	 case c_reduce_gen_container: //generovani kontejneru
	    {
	       lalr_stack_element_s &lse = lalr_stack[lalr_stack.used - 3];

	       unsigned tmp_char_idx = lse.third_num;
	       char tmp_char = def_code.data[tmp_char_idx];
	       def_code.data[tmp_char_idx] = '\0';

	       string_s cont_name;
	       cont_name.size = lse.third_num - lse.second_num + 1;
	       cont_name.data = def_code.data + lse.second_num;

	       ((processor_s *)processor_ptr)->generate_container_def(cont_name,cont_params);

	       def_code.data[tmp_char_idx] = tmp_char;

	       cont_params[c_param_types].used = 0;
	       cont_params[c_param_variables].used = 0;
	       cont_params[c_param_compare].used = 0;
	       cont_params[c_param_functions].used = 0;
	       cont_params[c_param_names].used = 0;
	    }
	    break;
	 case c_reduce_set_types: //datove typy
	    type_var_trigger = c_param_types;
	    break;
	 case c_reduce_set_variables: //nazvy promennych
	    type_var_trigger = c_param_variables;
	    break;
	 case c_reduce_set_compare:
	    type_var_trigger = c_param_compare;
	    break;
	 case c_reduce_element_second: //nastaveni hodnoty typu nebo promenne
	 case c_reduce_element_first:
	    {
	       string_array_s &param = cont_params[type_var_trigger];
	       lalr_stack_element_s &lse = lalr_stack.last();

	       param.push_blank();
	       param.last().set(lse.third_num - lse.second_num,def_code.data + lse.second_num);
	    }
	    break;
	 case c_reduce_function: //nastaveni popisu definice funkce
	    {
	       string_array_s &param = cont_params[c_param_functions];
	       lalr_stack_element_s &lse = lalr_stack.last();
	       
	       param.push_blank();
	       param.last().set((lse.third_num - lse.second_num) - 2,def_code.data + lse.second_num + 1);
	    }
	    break;
	 case c_reduce_name: //alternativni jmena struktury
	    {
	       string_array_s &param = cont_params[c_param_names];
	       lalr_stack_element_s &lse = lalr_stack.last();
	       
	       param.push_blank();
	       param.last().set(lse.third_num - lse.second_num,def_code.data + lse.second_num);
	    }
	    break;
	 }

         // - odstraneni tela pravidla z vrcholu zasobniku -
         lalr_stack.used -= rule_body_lengths[parse_action];

         // - ulozeni noveho stavu automatu na zasobnik -
         unsigned goto_val = lalr_table[lalr_stack.last().first_num*c_terminal_plus_nonterminal_cnt + rule_head_idxs[parse_action]];
         lalr_stack.push(goto_val);
      }

   } while(1);
}

void process_s::run_on(char *file_name)
{
   cont_params.copy_resize(5);
   cont_params.used = 5;

   assert(source_string.load_text_file(file_name));
   source_idx = 0;

   /*
    * nalezeni a zpracovani definici kontejneru ve zdrojovych souborech
    */

   do {
      //unsigned left_size = source_string.size - 1 - source_idx;
      //char *b_ptr = (char *)memmem(source_string.data + source_idx,left_size,c_begin,c_begin_len);
      char *b_ptr = strstr(source_string.data + source_idx,c_begin);

      if (b_ptr == NULL) {
	 printf("%s",source_string.data + source_idx);
	 break;
      }
      else {
	 *b_ptr = '\0';
	 printf("%s",source_string.data + source_idx);
	 *b_ptr = c_begin[0];

	 source_idx = b_ptr - source_string.data;
	 //left_size = source_string.size - 1 - source_idx;
	 //char *e_ptr = (char *)memmem(source_string.data + source_idx,left_size,c_end,c_end_len);
	 char *e_ptr = strstr(source_string.data + source_idx,c_end);

	 assert(e_ptr != NULL);

	 unsigned tmp_char_idx = (e_ptr - b_ptr) + c_end_len;
	 char tmp_char = b_ptr[tmp_char_idx];

	 b_ptr[tmp_char_idx] = '\0';

	 string_s def_code;
	 def_code.size = (e_ptr - b_ptr) + c_end_len + 1;
	 def_code.data = b_ptr;
	 parse_def_code(def_code);
	 b_ptr[tmp_char_idx] = tmp_char;

	 source_idx = e_ptr - source_string.data + c_end_len;
	 //left_size = source_string.size - 1 - source_idx;
      }
   } while(1);
}



/*
 * main funkce
 */

int main(int argc,char **argv)
{
   mc_init();

   {
      assert(argc > 1);

      processor_s proc;
      proc.init();
      proc.init_processor();

      proc.run(argv[1]);

      char dta_file_name[256];
      unsigned dta_file_name_length = snprintf(dta_file_name,256,"%s.dta",argv[1]);
      assert(dta_file_name_length < 256);

      proc.save_data(dta_file_name);

      proc.clear();
   }

   mc_clear();
}

#endif

