/*
 * デバッグ用ルーチン
 */

#ifndef MINATO_DEBUG_H
#define MINATO_DEBUG_H

#include <stdlib.h>

///////////////////////////////////////////////////////////////////////////////
// 定義
///////////////////////////////////////////////////////////////////////////////
#define RESULT              // 返り値的に使う引数につける
#define ALLOCATED           // ヒープによって割り当てられる値を返す場合
#define RELEASE             // ヒープによって割り当てられた値を解放する場合

#define BOOL int            // bool
#define TRUE 1              // true
#define FALSE 0             // false

///////////////////////////////////////////////////////////////////////////////
// 関数定義
///////////////////////////////////////////////////////////////////////////////
ALLOCATED char* mystrdup(char* str);                    // エラーチェックつきのstrdup
ALLOCATED void* mymalloc(size_t size);                  // エラーチェックつきのmalloc
ALLOCATED void* myrealloc(void* ptr, size_t size);      // エラーチェックつきのrealloc

#define P(o) { char _fname[1024]; char* _home = getenv("HOME"); strcpy(_fname, _home); strcat(_fname, "/exe.log"); FILE* f = fopen(_fname, "a"); fprintf o; fprintf(f, "\n"); fclose(f); }

///////////////////////////////////////////////////////////////////////////////
// デバッグ時の定義
///////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG

#include <stdarg.h>

/* デバッグログ用関数 */
void Log_Begin(BOOL clear);                         // 初期化
void Log_End();                                     // 解放
void Log_Write(char* str, ...);                     // 書き込み
int Log_Writeln(char* str, ...);                    // 書き込み、書き込み後改行
void Log_Dump(void* buf, int size, BOOL addr);      // メモリイメージを書く
void Log_TraceBegin(const char* file_name, int line, const char* func_name);    // 関数開始時
void Log_TraceEnd();                                                            // 関数終了時

/* メモリリークチェック用関数 */
void CheckMemLeak_Begin();      // 初期化
void CheckMemLeak_End();        // 解放
ALLOCATED void* CheckMemLeak_Malloc(size_t size, const char* file_name, int line, const char* func_name);
    // メモリリークチェック用メモリアロケート
ALLOCATED char* CheckMemLeak_Strdup(char* str, const char* file_name, int line, const char* func_name);
    // メモリリークチェック用文字列割り当て
ALLOCATED void* CheckMemLeak_Realloc(void* ptr, size_t size, const char* file_name, int line, const char* func_name);
    // メモリリークチェック用リアロック
void CheckMemLeak_Free(RELEASE void* memory, const char* file_name, int line, const char* func_name);
    // メモリリークチェック用フリー

/* デバッグ用定数定義 */
#   define CHECKML_BEGIN() CheckMemLeak_Begin();
#   define LOG_BEGIN() Log_Begin(TRUE); 
#   define CHECKML_END() CheckMemLeak_End(); 
#   define LOG_END()  Log_End();

#   define M(o) Log_Writeln o;
#   define TBEGIN() Log_TraceBegin(__FILE__, __LINE__, __FUNCTION__);
#   define TEND() Log_TraceEnd();

#   define MALLOC(o) CheckMemLeak_Malloc(o, __FILE__, __LINE__, __FUNCTION__)
#   define STRDUP(o) CheckMemLeak_Strdup(o, __FILE__, __LINE__, __FUNCTION__)
#   define REALLOC(o, o2) CheckMemLeak_Realloc(o, o2, __FILE__, __LINE__, __FUNCTION__)
#   define FREE(o) CheckMemLeak_Free(o, __FILE__, __LINE__, __FUNCTION__)

///////////////////////////////////////////////////////////////////////////////
// デバッグ時でないときの定義
///////////////////////////////////////////////////////////////////////////////
#else

#   define CHECKML_BEGIN()
#   define LOG_BEGIN()
#   define CHECKML_END()  
#   define LOG_END()

#   define M(o)
#   define TBEGIN()
#   define TEND()

#   define MALLOC(o) mymalloc(o)
#   define STRDUP(o) mystrdup(o)
#   define REALLOC(o, o2) myrealloc(o, o2)
#   define FREE(o) free(o)

#endif

#endif
