/*******************************************************************
**                                                                **
**  Knihovna pro kontrolu práce s alokovanou pamětí a se soubory  **
**  Autor: Pavel Šabatka a Petr Petyovský                         **
**  Implementováno v rámci bakalářské práce                       **
**  VUT v Brně, FEKT v ak. roce 2007, 2008, 2010, 2011, 2012      **
**  rel. 2012.5                                                   **
**                                                                **
*******************************************************************/
/* $Id: check.cpp 40 2012-05-10 12:01:25Z xproch71 $ */
#include "stdafx.h"
#include "check.h"

#define CHECKER_TRUE 1
#define CHECKER_FALSE 0
#define CHECKER_BOOL short int

#undef malloc
#undef calloc
#undef realloc
#undef free
#undef fopen
#undef fclose

#ifdef __cplusplus
	#undef new
	#undef delete
#endif /* __cplusplus */

/* include knihoven */
#include <string.h>
#include <math.h>


/****************************
*      DATOVE TYPY          *
****************************/
enum TAllocType {EMalloc = 0, ECalloc, ERealloc, ENew, ENewA, ENewNothrow, ENewNothrowA, ECount};
static const char *alloc_type_str[ECount] = {"malloc", "calloc", "realloc", "new", "new[]", "new(nothrow)", "new(nothrow)[]"};

//  prvek seznamu
struct TNodeMem 
	{
	void* memory_address;	// adresa alokovane pameti
	size_t size;			// alokovana velikost
	char file[__CHECKER_MAXLENGTH_FILENAME__];
	char func[__CHECKER_MAXLENGTH_FUNCNAME__];
	unsigned int linenum;	// radek zdrojoveho kodu (makro __LINE__)
	int alloc_num;			// absolutni poradi alokace
	enum TAllocType type_func;

	struct TNodeMem *ptr;		// ukazatel na dalsi prvek
	};    //  linearni seznam

struct TListMem 
	{
	TNodeMem *act;
	TNodeMem *first;
		
	// statistiky programu
	unsigned int count_alloc;
	unsigned int count_free;
	size_t size_alloc;
	size_t size_free;
	};

struct TNodeFile 
	{
	char file[__CHECKER_MAXLENGTH_FILENAME__];		// soubor, ve kterem je volano fopen
	char func[__CHECKER_MAXLENGTH_FUNCNAME__];	// funkce, ve ktere je volano fopen
	unsigned int linenum;			// radek zdrojoveho kodu (makro __LINE__)
	char path[__CHECKER_MAXLENGTH_PATHNAME__];		// jmeno souboru
	char mode[__CHECKER_MAXLENGTH_FILEMODE__];	// parametry otevirani souboru
	FILE *memory_address;			// adresa handleru FILE

	struct TNodeFile *ptr;		// ukazatel na dalsi prvek
	};

struct TListFile 
	{
	TNodeFile *act;
	TNodeFile *first;

	// statistiky programu
	unsigned int count_fopen;
	unsigned int count_fclose;
	};

/****************************
*          FUNKCE           *
****************************/
//  prace se seznamem - funkce pro kontrolu alokace v C
static void allocc_init_list(struct TListMem *aLm);					// inicializace
static void allocc_insert(struct TListMem*, size_t, void*, unsigned int, const char[], const char [], enum TAllocType);	// vlozeni prvku
static void allocc_dispose_act(struct TListMem *L);				// zrusi aktualni prvek
static void allocc_set_act(struct TListMem *L, void *address);		// nastavi prvek se zadanou adresou jako aktualni
static void allocc_set_last_act(struct TListMem *L);				// nastavi posledni prvek jako aktualni
static int  allocc_active(const struct TListMem *L);				// overi, jestli je seznam aktivni

// prace se seznamem - funkce pro kontrolu souboru v C
static void filec_init_list(struct TListFile *LS);				// inicializace
static void filec_insert(struct TListFile *, const char [], const char [], unsigned int, const char [], const char [], FILE *); // vlozeni prvku
static void filec_dispose_act(struct TListFile *L);			// zrusi aktualni prvek
static void filec_set_act(struct TListFile *L, FILE *adress);	// nastavi prvek se zadanou adresou jako aktualni
static void filec_set_last_act(struct TListFile *L);			// nastavi posledni prvek jako aktualni
static int  filec_active(const struct TListFile *L);			// overi, jestli je seznam aktivni

// prace se seznamem - pro oba seznamy
static void dispose_lists (struct TListMem*, struct TListFile *);		// zruseni vsech seznamu

// dalsi funkce
static void checkdel(void);								// tuto funkci pridavam do funkce exit
static void program_error(void);						// vyvola chybu, korektne uvolni pamet a soubory, ukonci program
static void print_lists(struct TListMem*, struct TListFile*, int, int);	// vypise statistiky programu

/***************************************
*  IMPLEMENTACE STATICKYCH PROMENNYCH  *
****************************************/
static struct TListMem L;						// seznam alokovane pameti
static struct TListFile LF;						// seznam otevrenych souboru
static CHECKER_BOOL used_alloc =  CHECKER_FALSE;	// bool - byla jiz alokovana nejaka pamet?
static CHECKER_BOOL used_file_c = CHECKER_FALSE;	// bool - byl jiz otevren nejaky soubor?
static CHECKER_BOOL correct_exit = CHECKER_TRUE;	// bool - byl program ukoncen bez chyby

// Mailbox pro docasne ulozeni _LINE_ _FILE_ _FUNC_ hodnot pri volani operatoru delete
static CHECKER_BOOL chk_delete_record_full = CHECKER_FALSE;  // bool - Je ulozen v temp delete mailboxu nejaky zaznam?
static unsigned int chk_delete_line = 0;
static char chk_delete_soubor[__CHECKER_MAXLENGTH_FILENAME__] = {'\0'};
static char chk_delete_func[__CHECKER_MAXLENGTH_FUNCNAME__] = {'\0'};

// Mailbox pro docasne ulozeni _LINE_ _FILE_ _FUNC_ hodnot pri volani operatoru new
static CHECKER_BOOL chk_new_record_full = CHECKER_FALSE;  // bool - Je ulozen v temp delete mailboxu nejaky zaznam?
static unsigned int chk_new_line = 0;
static char chk_new_soubor[__CHECKER_MAXLENGTH_FILENAME__] = {'\0'};
static char chk_new_func[__CHECKER_MAXLENGTH_FUNCNAME__] = {'\0'};

/********************************************
*  IMPLEMENTACE FUNKCI  - UZIVATELSKYCH     *
********************************************/
void my_stat(unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	printf("%s: %u :%s\n" ,soubor, line, func);
	// vypise alokovanou pamet a otevrene soubory
	print_lists(&L, &LF, CHECKER_TRUE, CHECKER_TRUE);
	}

void my_memory_stat (unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	printf("%s: %u :%s\n" ,soubor, line, func);
	// vypise aktualni stav alokovane pameti
	print_lists(&L, &LF, CHECKER_TRUE, CHECKER_FALSE);
	}

void my_file_stat (unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	printf("%s:%u:%s\n", soubor, line, func);
	//  vypise aktualni otevrene soubory
	print_lists(&L, &LF, CHECKER_FALSE, CHECKER_TRUE);
	}

const bool my_delete_recorder(unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__])
	{
	if(chk_delete_record_full == CHECKER_TRUE)
		fprintf(CHECKER_OUT, "Delete record mailbox isn't empty:\ndelete(%s:%u:%s)\n<-\ndelete(%s:%u:%s)\n", 
				chk_delete_soubor, chk_delete_line, chk_delete_func, soubor, line, func);
	chk_delete_line = line;
	strncpy(chk_delete_soubor, soubor, __CHECKER_MAXLENGTH_FILENAME__);
	strncpy(chk_delete_func, func, __CHECKER_MAXLENGTH_FUNCNAME__);
	chk_delete_record_full = CHECKER_TRUE;
	return(false);
	}

const bool my_new_recorder(unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__])
{
	if(chk_new_record_full == CHECKER_TRUE)
		fprintf(CHECKER_OUT, "New record mailbox isn't empty:\nnew(%s:%u:%s)\n<-\nnew(%s:%u:%s)\n", 
				chk_new_soubor, chk_new_line, chk_new_func, soubor, line, func);
	chk_new_line = line;
	strncpy(chk_new_soubor, soubor, __CHECKER_MAXLENGTH_FILENAME__);
	strncpy(chk_new_func, func, __CHECKER_MAXLENGTH_FUNCNAME__);
	chk_new_record_full = CHECKER_TRUE;
	return(false);
}

/***************************************************
*  IMPLEMENTACE ALOKACNICH DEALOKACNICH FUNKCI - C *
***************************************************/
void* my_malloc(size_t size, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	void *novyPtr = NULL;
	if (used_alloc == CHECKER_FALSE) 
		{
		used_alloc = CHECKER_TRUE;
		allocc_init_list(&L);
		
		if (used_file_c == CHECKER_FALSE) 
			atexit(&checkdel);
		}
		
	novyPtr = (void *) malloc(size);

	if (novyPtr) 
		{
		allocc_insert(&L, size, novyPtr, line, soubor, func, EMalloc);
		L.count_alloc++;
		L.size_alloc += size;
		}
	else 
		{
		fprintf(CHECKER_OUT,  "Pri alokaci pameti nastala chyba !\n"
				              "---------------------------------\n"
							  "Chyba pri volani funkce void* malloc(size_t)\n"
				);
		}
	return novyPtr;
	}

void* my_calloc(size_t count, size_t size, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	void *novyPtr = NULL;
	if (used_alloc == CHECKER_FALSE) 
		{
		used_alloc = CHECKER_TRUE;
		allocc_init_list(&L);
		if (used_file_c == CHECKER_FALSE)
			atexit(&checkdel);
		}

	novyPtr = (void *) calloc(count, size);

	if (novyPtr) 
		{
		allocc_insert (&L, size*count, novyPtr, line, soubor, func, ECalloc);
		L.count_alloc++;
		L.size_alloc += (size*count);
		}
	else 
		{
		fprintf(CHECKER_OUT,  "Pri alokaci pameti nastala chyba !\n"
							  "------------------------------\n"
				              "Chyba pri volani funkce void* calloc(size_t, size_t)\n"
				);
		}

	return novyPtr;
	}

void* my_realloc(void* realloc_ptr, size_t size, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	void *newPtr = NULL;
#if 0
	if (size < 0) 			// toto je zadany nesmysl
		{
		fprintf(CHECKER_OUT,  "CHECKER:\nChyba - pri volani funkce  void* REALLOC (void *, size_t) byl zadan druhy parametr zaporny\nFunkce nealokovala ani neuvolnila zadnou pamet\n\n");
		}
	else 
#endif
	if (size == 0) 		// tzn. jiny zapis funkce free
		{
		allocc_set_act(&L, realloc_ptr);

		if (allocc_active(&L)) 		// uvolnuji korektne pridelenou pamet
			{
			L.count_free++;
			L.size_free += L.act->size;
			allocc_dispose_act(&L);
			free (realloc_ptr);
			}
		else 					// uvolnuji pamet, ktera mi nebyla pridelena
			{
			fprintf(CHECKER_OUT,  "\n\nCHECKER: CHYBA\n------------------------------\n");
			fprintf(CHECKER_OUT,  "Volanim funkce\nvoid realloc(void*, size_t)\nse pokousite uvolnit pamet na adrese: %p, ktera Vam nebyla pridelena.\n", realloc_ptr);
			fprintf(CHECKER_OUT,  "\n-------------------------------------\n");
			fprintf(CHECKER_OUT,  "Lokace chyby:\n");
			fprintf(CHECKER_OUT,  "%u radek zdrojoveho kodu v souboru %s\n", line, soubor);
			fprintf(CHECKER_OUT,  "volani funkce %s\n", func);
			fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
			program_error();
			}
		}  // size == 0
	else 				// budeme pracovat s pameti (alokovat / realokovat)
		{
		if (realloc_ptr == NULL) // tj. jiny zapis funkce malloc
			{
			if (used_alloc == CHECKER_FALSE) 	// jestlize jeste nebylo alokovano
				{
				used_alloc = CHECKER_TRUE;
				allocc_init_list(&L);
				if (used_file_c == CHECKER_FALSE) 
					atexit(&checkdel);
				}
			newPtr = (void *) malloc(size);
			if (newPtr) 			// 
				{
				allocc_insert (&L, size, newPtr, line, soubor, func, ERealloc);
				L.count_alloc++;
				L.size_alloc += size;
				}
			else 
				{
				fprintf(CHECKER_OUT,  "CHECKER: Pri alokaci pameti nastala chyba !\n------------------------------\nChyba pri volani funkce void* realloc(void *, size_t,)");
				}
			} // if (realloc_ptr == NULL)
		else 				// volani funkce realloc
			{
			allocc_set_act (&L, realloc_ptr);
			if (!allocc_active(&L)) 
				{
				fprintf(CHECKER_OUT,  "\n\nCHECKER: Chyba - prvni parametr funkce\n void* realloc (void*, size_t) \nzadavate ukazatel na misto v pameti, ktere vam nebylo prideleno ! !\n-----------------------------------------------------\n");
				return NULL;
				}
			newPtr = (void *) realloc(realloc_ptr, size);
			if (newPtr != NULL) 
				{			
				L.size_alloc -= (L.act->size) + (size);
				allocc_dispose_act(&L);
				allocc_insert (&L, size, newPtr, line, soubor, func, ERealloc);
				}
			else 
				{
				fprintf(CHECKER_OUT,  "CHECKER: Pri alokaci pameti nastala chyba !\n------------------------------\nChyba pri volani funkce void* realloc(void *, size_t,)");
				}
			} // else - if (realloc_ptr != NULL)
		return newPtr;
		} // else - if (size > 0)
	return NULL;
	}

void my_free(void *Ptr, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char name_fce[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	allocc_set_act(&L, Ptr);

	if (allocc_active(&L)) 
		{
		if ( (L.act->type_func == ENew) || (L.act->type_func == ENewA) || (L.act->type_func == ENewNothrow) || (L.act->type_func == ENewNothrowA)) 
			{
			fprintf(CHECKER_OUT,  "\n\nCHECKER: VAROVANI\nFunkci free() uvolnujete pamet, ktera byla alokovana operatorem %s(). Spravne by mela byt uvolnena operatorem delete%s(). Pozor, pamet nebyla uvolnena.\n\n", alloc_type_str[L.act->type_func], ( (L.act->type_func == ENewA) || (L.act->type_func == ENewNothrowA) )? ("[]") : (""));
			fprintf(CHECKER_OUT,  "------------------------------\n"
								  "Lokace varovani:\n"
								  "%u radek zdrojoveho kodu v souboru %s\n", line, soubor);
			fprintf(CHECKER_OUT,  "volani funkce %s\n", name_fce);
			fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
			}
		else 
			{
			L.count_free++;
			L.size_free += L.act->size;
			allocc_dispose_act(&L);
			free(Ptr);
			}
		}
	else 
		{
		fprintf(CHECKER_OUT,  "\n\nCHECKER: CHYBA\n------------------------------\n"
				              "Volanim funkce\nvoid free(void*)\nse pokousite uvolnit pamet na adrese: %p, ktera Vam nebyla pridelena.\n", Ptr);
		
		fprintf(CHECKER_OUT,  "------------------------------\n"
							  "Lokace chyby:\n"
							  "%u radek zdrojoveho kodu v souboru %s\n", line, soubor);
		fprintf(CHECKER_OUT,  "volani funkce %s\n", name_fce);
		fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
		program_error();
		}
	}


/****************************************************
*  IMPLEMENTACE ALOKACNI / DEALOKACNI OPERATORU - C++ *
****************************************************/
#ifdef __cplusplus

void* operator new(size_t aSize) /* throw(std::bad_alloc) */
	{
	void *addr = NULL;
	
	if (used_alloc == CHECKER_FALSE) 
		{
		used_alloc = CHECKER_TRUE;
		allocc_init_list(&L);
		if(used_file_c == CHECKER_FALSE) 
			atexit(&checkdel);
		}
	addr = (void *) malloc(aSize);
	if (addr) 
		{
		if(chk_new_record_full)
			allocc_insert (&L, aSize, addr, chk_new_line, chk_new_soubor, chk_new_func, ENew);
		else
			allocc_insert (&L, aSize, addr, 0, "library call", "hidden new", ENew);
			
		L.count_alloc++;
		L.size_alloc += aSize;
		}
	else 
		{
		fprintf(CHECKER_OUT, "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new(size_t)");
		throw std::bad_alloc();
		}
	chk_new_record_full = CHECKER_FALSE;
	return(addr);
	}	

void* operator new(size_t aSize, const std::nothrow_t&) throw()
	{
		{
		void *addr = NULL;
		
		if (used_alloc == CHECKER_FALSE) 
			{
			used_alloc = CHECKER_TRUE;
			allocc_init_list(&L);
			if (used_file_c == CHECKER_FALSE) 
				atexit(&checkdel);
			}
		addr = (void *) malloc(aSize);
		
		if(addr) 
			{
			if(chk_new_record_full)
				allocc_insert (&L, aSize, addr, chk_new_line, chk_new_soubor, chk_new_func, ENewNothrow);
			else
				allocc_insert (&L, aSize, addr, 0, "library call", "hidden new", ENewNothrow);
			
			L.count_alloc++;
			L.size_alloc += aSize;
			}
		else 
			{
			fprintf(CHECKER_OUT, "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new(size_t,nothrow)");
			}
		chk_new_record_full = CHECKER_FALSE;
		return(addr);
		}	
	}

void* operator new[](size_t aSize) /* throw(std::bad_alloc) */
	{
	void *addr = NULL;
	
	if (used_alloc == CHECKER_FALSE) 
		{
		used_alloc = CHECKER_TRUE;
		allocc_init_list(&L);
		if(used_file_c == CHECKER_FALSE) 
			atexit(&checkdel);
			}
	addr = (void *) malloc(aSize);
	if (addr) 
		{
		if(chk_new_record_full)
			allocc_insert (&L, aSize, addr, chk_new_line, chk_new_soubor, chk_new_func, ENewA);
			else
				allocc_insert (&L, aSize, addr, 0, "library call", "hidden new", ENewA);
				
				L.count_alloc++;
		L.size_alloc += aSize;
		}
	else 
		{
		fprintf(CHECKER_OUT, "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new[](size_t)");
		throw std::bad_alloc();
		}
	chk_new_record_full = CHECKER_FALSE;
	return(addr);
	}	

void* operator new[](size_t aSize, const std::nothrow_t&) throw()
	{
	void *addr = NULL;
	
	if (used_alloc == CHECKER_FALSE) 
		{
		used_alloc = CHECKER_TRUE;
		allocc_init_list(&L);
		if(used_file_c == CHECKER_FALSE) 
			atexit(&checkdel);
			}
	addr = (void *) malloc(aSize);
	if (addr) 
		{
		if(chk_new_record_full)
			allocc_insert (&L, aSize, addr, chk_new_line, chk_new_soubor, chk_new_func, ENewNothrowA);
			else
				allocc_insert (&L, aSize, addr, 0, "library call", "hidden new", ENewNothrowA);
				
				L.count_alloc++;
		L.size_alloc += aSize;
		}
	else 
		{
		fprintf(CHECKER_OUT,  "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new[](size_t,nothrow)");
		}
	chk_new_record_full = CHECKER_FALSE;
	return(addr);
	}	

//void* operator new(size_t size, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FILENAME__]) /* throw(std::bad_alloc) */
//	{	
//	void *novyPtr = NULL;
//	
//	if (used_alloc == CHECKER_FALSE) 
//		{
//		used_alloc = CHECKER_TRUE;
//		allocc_init_list(&L);
//		if (used_file_c == CHECKER_FALSE) 
//			atexit(&checkdel);
//		}
//	novyPtr = (void *) malloc(size);
//	
//	if (novyPtr) {
//		allocc_insert (&L, size, novyPtr, line, soubor, func, ENew);
//		L.count_alloc++;
//		L.size_alloc += size;
//		}
//	else 
//		{
//		fprintf(CHECKER_OUT,  "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new(size_t)");
//		throw std::bad_alloc();
//		}
//	return novyPtr;
//	}

//void* operator new[](size_t size, unsigned int line, const char soubor[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FILENAME__]) /* throw(std::bad_alloc) */
//	{	
//	void *novyPtr = NULL;
//	if(used_alloc == CHECKER_FALSE) 
//		{
//		used_alloc = CHECKER_TRUE;
//		allocc_init_list(&L);
//		if(used_file_c == CHECKER_FALSE) 
//			atexit(&checkdel);
//		}
//
//	novyPtr = (void *) malloc(size);
//	
//	if(novyPtr)
//		{
//		allocc_insert (&L, size, novyPtr, line, soubor, func, ENewA);
//		L.count_alloc++;
//		L.size_alloc += size;
//		}
//	else
//		{
//		fprintf(CHECKER_OUT,  "Pri alokaci pameti nastala chyba !\n---------------------------------\nChyba pri alokaci pomoci operatoru void* operator new[](size_t)");
//		throw std::bad_alloc();
//		}
//	return novyPtr;
//	}

void delet_routine(void *Ptr) throw()
	{
	allocc_set_act(&L, Ptr);

	if (allocc_active(&L)) 
		{
		if( (L.act->type_func != ENew) && (L.act->type_func != ENewNothrow) ) 
			{
			fprintf(CHECKER_OUT,  "\n\nCHECKER: VAROVANI\nOperatorem delete() uvolnujete pamet, ktera byla alokovana pomoci %s(). Spravne by mela byt uvolnena pomoci %s().\n\n", alloc_type_str[L.act->type_func], ((L.act->type_func == ENewA) || (L.act->type_func == ENewNothrowA)) ? ("delete[]") : ("free") );
			if(chk_delete_record_full)
				{
				fprintf(CHECKER_OUT,  "------------------------------\n"
						"Lokace chyby:\n"
						"%u radek zdrojoveho kodu v souboru %s\n", chk_delete_line, chk_delete_soubor);
				fprintf(CHECKER_OUT,  "volani funkce %s\n", chk_delete_func);
				fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
				}
			}
		else 
			{
			L.count_free++;
			L.size_free += L.act->size;
			allocc_dispose_act(&L);
			free(Ptr);
			}
		}
	else 
		{
		fprintf(CHECKER_OUT,  "\n\nCHECKER: CHYBA\n------------------------------\n"
				"Volanim operatoru \ndelete(void*)\nse pokousite uvolnit pamet na adrese: %p, ktera Vam nebyla pridelena.\n", Ptr);
		if(chk_delete_record_full)
			{
			fprintf(CHECKER_OUT,  "------------------------------\n"
					"Lokace chyby:\n"
					"%u radek zdrojoveho kodu v souboru %s\n", chk_delete_line, chk_delete_soubor);
			fprintf(CHECKER_OUT,  "volani funkce %s\n", chk_delete_func);
			fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
			}
		program_error();
		}
	chk_delete_record_full = CHECKER_FALSE;
	}

void operator delete(void *Ptr) throw() 
	{
	delet_routine(Ptr);
	}

//void operator delete(void *Ptr, unsigned int, const char[], const char[]) throw() 
//	{ /* Verze pro pripad, kdy je dealokovano automaticky uprostred c'toru diky vznikle vyjimce */
//	delet_routine(Ptr);
//	}

void delet_array_routine(void *Ptr) throw()
	{
	allocc_set_act(&L, Ptr);

	if (allocc_active(&L))
		{
		if( (L.act->type_func != ENewA) && (L.act->type_func != ENewNothrowA) )
			{
			fprintf(CHECKER_OUT,  "\n\nCHECKER: VAROVANI\nOperatorem delete[]() uvolnujete pamet, ktera byla alokovana pomoci %s(). Spravne by mela byt uvolnena pomoci %s().\n\n", alloc_type_str[L.act->type_func], ( (L.act->type_func == ENew) || (L.act->type_func == ENewNothrow)) ? ("delete") : ("free") );
			if(chk_delete_record_full)
				{
				fprintf(CHECKER_OUT,  "------------------------------\n"
						"Lokace chyby:\n"
						"%u radek zdrojoveho kodu v souboru %s\n", chk_delete_line, chk_delete_soubor);
				fprintf(CHECKER_OUT,  "volani funkce %s\n", chk_delete_func);
				fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
				}
			}
		else 
			{
			L.count_free++;
			L.size_free += L.act->size;
			allocc_dispose_act(&L);
			free(Ptr);
			}
		}
	else 
		{
		fprintf(CHECKER_OUT,  "\n\nCHECKER: CHYBA\n------------------------------\n"
				"Volanim operatoru \ndelete[](void*)\nse pokousite uvolnit pamet na adrese: %p, ktera Vam nebyla pridelena.\n", Ptr);
		if(chk_delete_record_full)
			{
			fprintf(CHECKER_OUT,  "------------------------------\n"
					"Lokace chyby:\n"
					"%u radek zdrojoveho kodu v souboru %s\n", chk_delete_line, chk_delete_soubor);
			fprintf(CHECKER_OUT,  "volani funkce %s\n", chk_delete_func);
			fprintf(CHECKER_OUT,  "celkove %u volani funkce void free(void *) v programu\n", L.count_free + 1);
			}
		program_error();
		}
	chk_delete_record_full = CHECKER_FALSE;	
	}

void operator delete[](void *Ptr) throw() 
	{
	delet_array_routine(Ptr);
	}

//void operator delete[](void *Ptr, unsigned int, const char[], const char[]) throw() 
//	{ /* Verze pro pripad kdy je dealokovano uprostred c'toru dynamicky vznikajiciho objektu diky vznikle vyjimce */
//	delet_array_routine(Ptr);
//	}

#endif /* __cplusplus */

/***************************************
*  IMPLEMENTACE SOUBOROVYCH FUNKCI - C *
****************************************/
FILE* my_fopen(const char file[__CHECKER_MAXLENGTH_PATHNAME__], const char mode[__CHECKER_MAXLENGTH_FILEMODE__], unsigned int line, const char filesource[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__]) 
	{
	FILE *novyPtr = NULL;
	if (used_file_c == CHECKER_FALSE) 
		{
		used_file_c = CHECKER_TRUE;
		filec_init_list(&LF);
		if (used_alloc == CHECKER_FALSE) atexit(&checkdel);
		}
		
	novyPtr = fopen(file, mode);

	if (novyPtr != NULL)
		{
		filec_insert (&LF, file, mode, line, filesource, func, novyPtr);
		LF.count_fopen++;
		}
	else
		{
		fprintf(CHECKER_OUT,  "CHECKER: CHYBA\nSoubor %s  se nepodarilo otevrit", file);
		}
	return novyPtr;
	}

int my_fclose(FILE* streamPtr, unsigned int line, const char file[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__])
	{
	int succ=0;

	filec_set_act(&LF, streamPtr);

	if (filec_active(&LF))
		{
		LF.count_fclose++;
		succ = fclose (streamPtr);
		filec_dispose_act(&LF);
		}
	else
		{
		fprintf(CHECKER_OUT,  "\n\nCHECKER: CHYBA\n------------------------------\n");
		fprintf(CHECKER_OUT,  "Volanim funkce\nint fclose(FILE*)\nse pokousite uzavrit soubor, ktery nebyl neotevren\n");
		fprintf(CHECKER_OUT,  "\n---------------------------------------\n");
		fprintf(CHECKER_OUT,  "Lokace chyby:\n");
		fprintf(CHECKER_OUT,  "%u radek zdrojoveho kodu v souboru %s\n", line, file);
		fprintf(CHECKER_OUT,  "volani funkce %s\n", func);
		program_error();
		}
	return succ;
	}


/*********************************************************/
/*                  PRACE SE SEZNAMEM                    */
/*********************************************************/

void checkdel(void)
	{
	/*
	tato funkce je pridavana do funkce exit
	v pripade, ze v programu nenastane fatalni chyba (uvolneni nealokovane pameti apod.),
	vypise statistiky programu pomoci print_list() a nasledne uvolni nevolnenou pamet
	a uzavre neuzavrene soubory pomoci funkce dispose_lists()
	*/
	
	if (correct_exit == CHECKER_TRUE) 
		print_lists(&L, &LF, CHECKER_TRUE, CHECKER_TRUE);
	dispose_lists(&L, &LF);
	}

void allocc_init_list(struct TListMem *aLm) 
	{
	/* inicializuje seznam pro alokace*/
	
	aLm->act = NULL;
	aLm->first = NULL;
	aLm->count_alloc = 0;
	aLm->count_free = 0;
	aLm->size_alloc = 0;
	aLm->size_free = 0;
	}

void filec_init_list (struct TListFile *aLf) 
	{
	/* inicializuje seznam pro soubory*/
	
	aLf->act = NULL;
	aLf->first = NULL;
	aLf->count_fopen = 0;
	aLf->count_fclose = 0;
	}

void allocc_insert (struct TListMem *L, size_t size, void* address, unsigned int line, const char file[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FUNCNAME__], enum TAllocType type_func) 
	{
	/* vlozi na konec seznamu prvek se zadanymi parametry
	   nastavi vlozeny prvek (tzn. posledni) jako aktualni
	*/
	
	char *c = NULL;
	char lomitko= '\\';
	TNodeMem *insPtr;
		
	insPtr = (TNodeMem *) malloc (sizeof(struct TNodeMem));

	if (!insPtr) 
		program_error();
	else	
		{
		insPtr->size = size;			// alokovana velikost
		insPtr->linenum = line;			// radek zdrojoveho kodu (makro __LINE__)
			
		c = strrchr((char *)file, lomitko);		// jmeno souboru (makro __FILE__)
		if (c != NULL) 
			{			// osetreni pro Windows
			strncpy(insPtr->file, (c+1), __CHECKER_MAXLENGTH_FILENAME__);	//__FILE__ vraci soubor i s cestou k nemu
			}
		else strncpy(insPtr->file, file, __CHECKER_MAXLENGTH_FILENAME__);	// pro Linux/Unix staci nakopirovat

		insPtr->alloc_num = L->count_alloc + 1;	// kolikate volani mallocu to je
		insPtr->memory_address = (int*)address;	// adresa alokovane pameti
		strncpy(insPtr->func, func, __CHECKER_MAXLENGTH_FUNCNAME__);		// jmeno nadrazene funkce (makro __CHECK_FUNC__)
		insPtr->type_func = type_func;

		insPtr->ptr = NULL;

		// vlozeni do seznamu
		if (L->first) 
			{
			// vlozeni na konec
			allocc_set_last_act(L);
			L->act->ptr = insPtr;
			L->act = insPtr;
			}
		else 
			{
			L->first = insPtr;
			L->act = insPtr;
			}
		}
	}
void filec_insert (struct TListFile *L, const char aPath[__CHECKER_MAXLENGTH_PATHNAME__], const char mode[__CHECKER_MAXLENGTH_FILEMODE__], unsigned int line, const char file[__CHECKER_MAXLENGTH_FILENAME__], const char func[__CHECKER_MAXLENGTH_FILENAME__], FILE *stream) {  // ok
/*
vlozi na konec seznamu prvek se zadanymi parametry
nastavi vlozeny prvek (tzn. posledni) jako aktualni
*/
	char *c = NULL;
	char lomitko = '\\';
	TNodeFile *insPtr;
	
	insPtr = (TNodeFile *) malloc (sizeof(struct TNodeFile));

	if (insPtr == NULL) program_error();
	else	
		{
		c = strrchr((char *)file, lomitko);		// jmeno souboru (makro __FILE__)
		if (c != NULL)					// osetreni pro Windows
			strncpy(insPtr->file, (c+1), __CHECKER_MAXLENGTH_FILENAME__);	//__FILE__ vraci soubor a cestu k nemu
		else strncpy(insPtr->file, file, __CHECKER_MAXLENGTH_FILENAME__);	// pro Linux/Unix staci nakopirovat


		strncpy(insPtr->func, func, __CHECKER_MAXLENGTH_FUNCNAME__);  // jmeno nadrazene funkce (makro __CHECK_FUNC__)


		insPtr->linenum = line;				// radek zdrojoveho kodu (makro __LINE__)

		c = strrchr((char *)aPath, lomitko);		// jmeno oteviraneho souboru
		if (c != NULL) strncpy(insPtr->path, (c+1), __CHECKER_MAXLENGTH_PATHNAME__);
		else strncpy(insPtr->path, aPath, __CHECKER_MAXLENGTH_PATHNAME__);

		strncpy(insPtr->mode, mode, __CHECKER_MAXLENGTH_FILEMODE__);// mod otvirani souboru

		insPtr->memory_address=stream;			   // adresa streamu

		insPtr->ptr = NULL;

		filec_set_last_act(L);			// vlozeni do seznamu
		if (L->act != NULL) 
			{
			L->act->ptr = insPtr;
			L->act = insPtr;
			}
		else 
			{
			L->first = insPtr;
			L->act = insPtr;
			}
		}
	}

void allocc_dispose_act(struct TListMem *L) 
	{
/*
zrusi aktivni prvek. 
Vazba z predchoziho se navaze na nasledujici prvek seznamu
nastavi aktivitu na prvni prvek
*/	
	if (allocc_active(L)) {
		if (L->act == L->first) 
			{			// jestli-ze je prvni
			if (L->act->ptr != NULL) 
				L->first=L->first->ptr;
			else 
				L->first = NULL;
			}
		else {						// jestli neni prvni, resim vazby
			TNodeMem *pom;

			pom=L->first;
			while (pom->ptr != L->act) pom=pom->ptr;

			pom->ptr=L->act->ptr;
			}
		free(L->act);
		L->act=L->first;
		}
	}

void filec_dispose_act(struct TListFile *L) 
	{
	/*
	zrusi aktivni prvek. 
	Vazba z predchoziho se navaze na nasledujici prvek seznamu
	nastavi aktivitu na prvni prvek
	*/	
	if (filec_active(L)) {
		if (L->act == L->first) {			// jestli-ze je prvni
			if (L->first->ptr != NULL) L->first=L->first->ptr;
			else L->first = NULL;
			}
		else {						// jestli neni prvni, resim vazby
			TNodeFile *pom;

			pom=L->first;
			while (pom->ptr != L->act) pom=pom->ptr;

			pom->ptr=L->act->ptr;
			}
		free (L->act);
		L->act=L->first;
		}
	}

void allocc_set_last_act(struct TListMem *L) 
	{
/*
nastavi jako aktualni prvek posledni prvek
jestli-ze nastane chyba, nastavi NULL
*/
	if (L->first != NULL) {	
		if (!allocc_active(L)) L->act=L->first;
		while (L->act->ptr != NULL) L->act = L->act->ptr;
		}
	else L->act = NULL;
	}

void filec_set_last_act (struct TListFile *L) 
	{
/*
nastavi jako aktualni prvek posledni prvek
jestli-ze nastane chyba, nastavi NULL
*/
	if (L->first != NULL) {	
		if (!filec_active(L)) L->act=L->first;
		while (L->act->ptr != NULL) L->act = L->act->ptr;
		}
	else L->act = NULL;
	}

void allocc_set_act(struct TListMem *aLm, void *aAddress) 
	{
	/*
	najde prvek se zadanou adresou. V pripade, 
	ze takovy prvek nenajde, nastavi aLm->act = NULL
	*/	
	for(aLm->act = aLm->first; (aLm->act) && (aLm->act->memory_address != aAddress);  aLm->act = aLm->act->ptr);	
	}

void filec_set_act(struct TListFile *aLf, FILE *aStream) 
	{
	/*
	najde prvek se zadanou adresou. V pripade, 
	ze takovy prvek nenajde, nastavi aLf->act = NULL
	*/	
	for(aLf->act = aLf->first; (aLf->act) && (aLf->act->memory_address != aStream);  aLf->act = aLf->act->ptr);
	}

int allocc_active(const struct TListMem *aLm)
	{
	/* jestli-ze je seznam aktivni, vraci 1, jinak 0 */
	return ((aLm->act) ? (CHECKER_TRUE) : (CHECKER_FALSE) );
	}

int filec_active(const struct TListFile *aLf) 
	{
	/* jestli-ze je seznam aktivni, vraci 1, jinak 0 */
	return ((aLf->act) ? (CHECKER_TRUE) : (CHECKER_FALSE) );
	}

void dispose_lists(struct TListMem* aLm, struct TListFile *aLf) 
	{		
	TNodeMem *pom;
	TNodeFile *pomf;

	while(aLm->first) 
		{
		pom = aLm->first;
		aLm->first = aLm->first->ptr;
		free(pom->memory_address); 	// uvolnim pamet alokovanou v programu
		free(pom);			// zrusim zaznam ze seznamu
		}
	aLm->first = NULL;
	aLm->act = NULL;

	while(aLf->first) 
		{
		pomf = aLf->first;
		aLf->first = aLf->first->ptr;
		fclose(pomf->memory_address);	// uzavru soubor
		free(pomf);			// zrusim zaznam ze seznamu
		}
	aLf->first = NULL;
	aLf->act = NULL;
	}

void program_error(void) 
	{
	fprintf(CHECKER_OUT,  "\nProgram musel byt ukoncen\n");
	correct_exit = CHECKER_FALSE;
	exit(EXIT_FAILURE);
	}

void print_lists(struct TListMem *L, struct TListFile *LF, int print_alloc, int print_file) 
	{
	int a=0, b=0, c=0, d=0, e=0, f=6;
	int mezer_mezi_sloupci, i=0, x=0;

   fprintf(CHECKER_OUT,  "\n\nCHECKER: KONTROLNI VYPIS \n=======================================================================\n");
   if (print_alloc && used_alloc) 
	{
	fprintf(CHECKER_OUT,  "VYPIS ALOKOVANE PAMETI\n");
	fprintf(CHECKER_OUT,  "Celkovy pocet alokaci pameti v programu: \t%u\n", L->count_alloc);
	fprintf(CHECKER_OUT,  "Celkovy pocet uvolneni pameti v programu: \t%u\n", L->count_free);
#if (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L)
       // velikost v C99 jiz definovan modifikator velikosti (%z) pro typ size_t
	   fprintf(CHECKER_OUT,  "Alokovano celkem  %zu  bytu, uvolneno  %zu  bytu\n", L->size_alloc, L->size_free);
#else
	   fprintf(CHECKER_OUT,  "Alokovano celkem  %lu  bytu, uvolneno  %lu  bytu\n", 
			   (unsigned long)L->size_alloc, (unsigned long)L->size_free);
#endif /* __STDC_VERSION__ */
	
	if (!L->first) 
		fprintf(CHECKER_OUT,  "Vsechna dynamicka pamet programu byla bez chyby uvolnena. :-)\n\n");
	else 
		{
#if (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L)		
		// velikost v C99 jiz definovan modifikator velikosti (%z) pro typ size_t
		fprintf(CHECKER_OUT,  "NEODALOKOVANO ZUSTAVA  %zd  BYTU !!!\n\n", L->size_alloc - L->size_free);
#else
		fprintf(CHECKER_OUT,  "NEODALOKOVANO ZUSTAVA  %ld  BYTU !!!\n\n", (long) L->size_alloc - (long) L->size_free);
#endif /* __STDC_VERSION__ */

		L->act = L->first;			//// ziskam delky nejdelsich udaju ////
		while (L->act) 
			{				// poradi alokace
			#ifdef __CHECKER_TAB_INDEX__
				x = 1 + (int) log10 ((float)L->act->alloc_num);
				if (x>a) a=x;
			#endif
			#ifdef __CHECKER_TAB_FILE_LINENUM__
				x = strlen(L->act->file);			// soubor
				if (x>b) b=x;
				x = 1 + (int) log10 ((float)L->act->linenum);	// radek
				if (x>c) c=x;
			#endif
			#ifdef __CHECKER_TAB_FUNCTION__
				x = strlen(L->act->func);			// funkce
				if (x>d) d=x;
				x = strlen(alloc_type_str[L->act->type_func % ECount]);
				if (x>f) f=x;
			#endif
			#ifdef __CHECKER_TAB_SIZE__
				x = 1 + (int) log10 ((float)L->act->size);	// velikost
				if (x>e) e=x;
			#endif
			L->act = L->act->ptr;
			}
			#ifdef __CHECKER_TAB_MEM_ADDR__ 
				i=22;
			#endif

		x = a+b+c+d+e+f+i;				// prizpusobeni sirky tabulky
		if (x<35) mezer_mezi_sloupci = 8;
		else if (x<40) mezer_mezi_sloupci = 7;
		else if (x<45) mezer_mezi_sloupci = 6;
		else if (x<50) mezer_mezi_sloupci = 5;
		else if (x<55) mezer_mezi_sloupci = 4;
		else if (x<60) mezer_mezi_sloupci = 3;
		else mezer_mezi_sloupci = 2;
									//////  zahlavi tabulky ////
		fprintf(CHECKER_OUT,  "VYPIS ALOKOVANE PAMETI\n");
		#ifdef __CHECKER_TAB_INDEX__
		fprintf(CHECKER_OUT,  "[n]");			// poradi alokace
			if (a < 1) a=1+mezer_mezi_sloupci;
			else a= a+mezer_mezi_sloupci;
			for (x=0; x<(a-3); x++) fprintf(CHECKER_OUT,  " ");
		#endif
		#ifdef __CHECKER_TAB_FILE_LINENUM__
		fprintf(CHECKER_OUT,  "soubor: radek");		// soubor: radek
			if (b+c+2 < 13) b= 13 + mezer_mezi_sloupci;
			else b = b+c+2+mezer_mezi_sloupci;
			for (x=0; x<(b-13); x++) fprintf(CHECKER_OUT,  " ");
		#endif
		#ifdef __CHECKER_TAB_FUNCTION__
		fprintf(CHECKER_OUT,  "funkce");			// funkce

		if (d > 0){
			d= d+4+f+2+mezer_mezi_sloupci;
			for (x=0; x<(d-6); x++) fprintf(CHECKER_OUT,  " ");
			}
		else {
			d= f + 2 + mezer_mezi_sloupci;
			for (x=0; x<(d-6); x++) fprintf(CHECKER_OUT,  " ");
			}
		#endif
		#ifdef __CHECKER_TAB_SIZE__
		fprintf(CHECKER_OUT,  "[b]");			// velikost
			if (e < 1) e=1 + mezer_mezi_sloupci;
			else e= e + mezer_mezi_sloupci;
			for (x=0; x<(e-3); x++) fprintf(CHECKER_OUT,  " ");
		#endif
		#ifdef __CHECKER_TAB_MEM_ADDR__ 
			fprintf(CHECKER_OUT,  "adresa pameti");
		#endif
			fprintf(CHECKER_OUT,  "\n-----------------------------------------------------------------------\n");
								////  telo tabulky ////
		L->act = L->first;
		while (L->act) 
			{
			#ifdef __CHECKER_TAB_INDEX__						// poradi alokace
			fprintf(CHECKER_OUT,  "%i", L->act->alloc_num);
				x=(a-1-(int) log10 ((float)L->act->alloc_num));
				for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			#ifdef __CHECKER_TAB_FILE_LINENUM__
			fprintf(CHECKER_OUT,  "%s: %u", L->act->file, L->act->linenum); // file: line
				x= (b- 3 - strlen(L->act->file) - (int) log10 ((float)L->act->linenum));
				for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			#ifdef __CHECKER_TAB_FUNCTION__
			if(strlen(L->act->func)) 
				{												// funkce
				fprintf(CHECKER_OUT,  "%s(): ", L->act->func);
				if (L->act->type_func == ERealloc) x = d - 4 - 7 - 2 - strlen(L->act->func);
				else if (L->act->type_func == ENew) x = d - 4 - 3 - 2 - strlen(L->act->func);
				else x = d - 4 - 6 - 2 - strlen(L->act->func);
				}
			else
				{
				if (L->act->type_func == ERealloc) x= d - 9;
				else if (L->act->type_func == ENew) x= d - 5;
				else x = d - 8;
				}
			
			fprintf(CHECKER_OUT,  "%s()", alloc_type_str[L->act->type_func]);

			for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			#ifdef __CHECKER_TAB_SIZE__
#if (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L)
			fprintf(CHECKER_OUT, "%zu", L->act->size);		// velikost v C99, definovan modifikator velikosti (%z) pro typ size_t
#else
			fprintf(CHECKER_OUT, "%lu", (unsigned long)L->act->size);		// velikost
#endif /* __STDC_VERSION__ */
				x=(e-1-(int) log10 ((float)L->act->size));
				for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			#ifdef __CHECKER_TAB_MEM_ADDR__ 
			fprintf(CHECKER_OUT, "%p -> %p", L->act->memory_address, (void*)((char*)L->act->memory_address+L->act->size));
			#endif
			fprintf(CHECKER_OUT, "\n");
			L->act = L->act->ptr;
			}
		fprintf(CHECKER_OUT, "\n");
		}
	}
	else if (print_alloc && !used_alloc) 
		{
		fprintf(CHECKER_OUT, "\nZadna pamet nebyla dynamicky alokovana\n\n");
		}
	
	
	if (print_file && used_file_c) {
		if (print_alloc) fprintf(CHECKER_OUT,  "\n-----------------------------------------------------------------------\n");
		fprintf(CHECKER_OUT,  "PREHLED OTEVRENYCH SOUBORU\n");
		fprintf(CHECKER_OUT,  "Pocet otevrenych souboru: \t%u\n", LF->count_fopen);
		fprintf(CHECKER_OUT,  "Pocet uzavrenych souboru: \t%u\n", LF->count_fclose);
		fprintf(CHECKER_OUT,  "NEUZAVRENYCH ZUSTAVA  %d  SOUBORU\n\n",LF->count_fopen-LF->count_fclose);
	
	     if (!LF->first) fprintf(CHECKER_OUT,  "Vsechny soubory byly bez chyby uzavreny\n\n");
	     else {

		LF->act=LF->first;			/* ziskam delky nejdelsich udaju */
		b=0; c=0; d=0; e=0; f=0;

		while (LF->act)
			{
			#ifdef __CHECKER_TAB_FILE_LINENUM__
				x = strlen(LF->act->file);			// soubor se zdrojovym kodem
				if (x>b) b=x;
				x = 1 + (int) log10 ((float)LF->act->linenum);	// radek
				if (x>c) c=x;
			#endif
			#ifdef __CHECKER_TAB_FUNCTION__
				x = strlen(LF->act->func);			// funkce
				if (x>d) d=x;
			#endif
				x = strlen(LF->act->path);			// otevirany soubor
				if (x>e) e=x;
				x = strlen(LF->act->mode);			// mod otevreni
				if (x>f) f=x;

			LF->act = LF->act->ptr;
			} /* while (LF->act != NULL) */

		x = b+c+d+e+f;						// prizpusobeni sirky tabulky
		if (x<25) mezer_mezi_sloupci = 8;
		else if (x<30) mezer_mezi_sloupci = 7;
		else if (x<35) mezer_mezi_sloupci = 6;
		else if (x<40) mezer_mezi_sloupci = 5;
		else if (x<45) mezer_mezi_sloupci = 4;
		else if (x<50) mezer_mezi_sloupci = 3;
		else mezer_mezi_sloupci = 2;
									//////  zahlavi tabulky ////
		fprintf(CHECKER_OUT,  "VYPIS OTEVRENYCH SOUBORU\n");

		#ifdef __CHECKER_TAB_FILE_LINENUM__
		fprintf(CHECKER_OUT,  "Misto otevreni");		// soubor: radek
			if (b+c+2 < 14) b= 14 + mezer_mezi_sloupci;
			else b = b+c+2+mezer_mezi_sloupci;
			for (x=0; x<(b-14); x++) fprintf(CHECKER_OUT,  " ");
		#endif
		#ifdef __CHECKER_TAB_FUNCTION__
		fprintf(CHECKER_OUT,  "Funkce");			// funkce

		if (d > 0){
			d= d+2+mezer_mezi_sloupci;
			for (x=0; x<(d-6); x++) fprintf(CHECKER_OUT,  " ");
			}

		#endif
		fprintf(CHECKER_OUT,  "Otevreny soubor");		// soubor: radek
			if (e < 15) e= 15 + mezer_mezi_sloupci;
			else e = e+mezer_mezi_sloupci;
			for (x=0; x<(e-15); x++) fprintf(CHECKER_OUT,  " ");
		fprintf(CHECKER_OUT,  "Mod otevreni");		// soubor: radek
			if (f < 12) f= 12 + mezer_mezi_sloupci;
			else f = f+mezer_mezi_sloupci;
			for (x=0; x<(f-12); x++) fprintf(CHECKER_OUT,  " ");
		
			fprintf(CHECKER_OUT,  "\n---------------------------------------------------------------------\n");
								////  telo tabulky ////
		LF->act=LF->first;
		while (LF->act != NULL) {
			#ifdef __CHECKER_TAB_FILE_LINENUM__
			fprintf(CHECKER_OUT,  "%s: %u", LF->act->file, LF->act->linenum); // file: line
				x= (b- 3 - strlen(LF->act->file) - (int) log10 ((float)LF->act->linenum));
				for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			#ifdef __CHECKER_TAB_FUNCTION__
			if (d > 0) 
				{
				if(strlen(LF->act->func))
					{									// funkce
					fprintf(CHECKER_OUT,  "%s()", LF->act->func);
					x = d - 2 - strlen(LF->act->func);
					}
				}
			for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			#endif
			if(strlen(LF->act->path)) 
				{										// nazev souboru
				fprintf(CHECKER_OUT,  "%s", LF->act->path);
				x = e - strlen(LF->act->path);
				}
			for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");
			if(strlen(LF->act->mode))
				{										// mod otevreni
				fprintf(CHECKER_OUT,  "%s", LF->act->mode);
				x = f - 2 - strlen(LF->act->mode);
				}
			for (i=0; i<x; i++) fprintf(CHECKER_OUT,  " ");

			fprintf(CHECKER_OUT, "\n");
			LF->act = LF->act->ptr;
			} /* while (LF->act != NULL) */
		fprintf(CHECKER_OUT,  "\n");
		} /* else - nejake soubory jeste nebyly uzavreny */
	} /* if (print_file && used_file_c) */
	fprintf(CHECKER_OUT,  "\n");
   } /* funkce print_list */

/* End of file check.c */
