/*
    Copyright (C) 2003 and onward Robert Muth <robert at muth dot org>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef BASIC_H
#define BASIC_H

#include <stdint.h>
// ========================================================================
#define GLOBALFUN extern
#define LOCALFUN static
#define MEMBERFUN

#define MEMBERVAR
#define GLOBALVAR
#define LOCALVAR static

#define LOCALTYPE
#define GLOBALTYPE


// ========================================================================
typedef int32_t INT32;
typedef int16_t INT16;
typedef uint32_t UINT32;
typedef uint16_t UINT16;
typedef uintptr_t PTRINT;

typedef bool BOOL;
typedef float FLT32;
typedef double FLT64;
typedef void VOID;
typedef char CHAR;


#ifndef TRUE
#define TRUE true
#endif

#ifndef FALSE
#define FALSE false
#endif


// ========================================================================
extern string StringHex( UINT32 val, UINT32 width = 0);

extern string StringDec( UINT32 val, UINT32 width = 0, CHAR padding = ' ');

extern string StringDecSigned( INT32 val, UINT32 width = 0, CHAR padding = ' ');

extern string StringDecSignedBignum( INT32 val, UINT32 width = 0, CHAR padding = ' ');

extern string StringHexBignum( UINT32 val, UINT32 width = 0, CHAR padding = ' ');

extern string StringFlt( FLT64 val, UINT32 precision = 0, UINT32 width = 0);

extern string StringBool(BOOL b);

// ========================================================================

inline string decstr(INT32 val, UINT32 width=0 )  {return StringDecSigned((INT32)val,width);}
inline string decstr(INT16 val, UINT32 width=0 )  {return StringDecSigned((INT32)val,width);}

inline string decstr(UINT32 val, UINT32 width=0 )  {return StringDec((INT32)val,width);}
inline string decstr(UINT16 val, UINT32 width=0 )  {return StringDec((INT32)val,width);}

inline string hexstr(INT32 val, UINT32 width=0 )  {return StringHex((INT32)val,width);}
inline string hexstr(INT16 val, UINT32 width=0 )  {return StringHex((INT32)val,width);}

inline string hexstr(UINT32 val, UINT32 width=0 )  {return StringHex((UINT32)val,width);}
inline string hexstr(UINT16 val, UINT32 width=0 )  {return StringHex((UINT32)val,width);}

inline string fltstr(FLT64 val, UINT32 prec=0,UINT32 width=0 )  {return StringFlt(val,prec,width);}

inline string ptrstr(const VOID *val )  {return StringHex(PTRINT(val));}
extern string ljstr(const string& s, UINT32 width, CHAR padding = ' ');

// ========================================================================


extern string Reformat(const string& s, const string& prefix, UINT32 min_line, UINT32 max_line);

extern UINT32 Tokenize(const string& line, string *array, UINT32 n);

// ========================================================================
extern const string Line1;
extern const string Line2;
extern const string Line3;
extern const string Line4;

// ========================================================================
extern VOID RegisterImageName(const string& name);

extern VOID InstallSignalHandlers();

extern VOID DisableMessage(UINT32 prefix);


extern VOID RegisterNewTrace( VOID (*foo) () );
extern VOID RegisterNewTerminate( VOID (*foo) () );
extern VOID RegisterNewResourceInfo( string (*foo) () );


extern string DefaultResinfo();

extern VOID DefaultTrace();

extern VOID DefaultTerminmate();


// ========================================================================
#define DO_RESINFO 1
#define DO_TERMINATE 1
#define DO_TRACE 1

extern VOID Message(const string& prefix,const string& message, BOOL term, BOOL trace, BOOL resinfo);

#define QMESSAGE(m,n,term,trace,resinfo) Message(n, m, term, trace, resinfo )
#define QMESSAGE_LIMIT(m,n,max,term,trace,resinfo) do{ static int qqq = 0; if( qqq++ >= max) break; \
                                               Message(n, m, term,trace,resinfo );}while(0)

#define ASSERTQ(message) QMESSAGE(message, "A: ",DO_TERMINATE, DO_TRACE, FALSE)

#if !defined(__GNUC__)
#define __FUNCTION__ ""
#endif

#define ASSERT(condition,message)   \
  do{ if(!(condition)) ASSERTQ( string(__FILE__)  + ":" +  __FUNCTION__  + ":" + decstr(__LINE__)  + ": " + message);}  while(0)

#define ASSERTX(condition) ASSERT(condition,"assertion failed: " #condition  "\n")
#define ASSERTZ(message)  ASSERT(0,message)

// below we have be trying to make each prefix unique

#define Error(message) QMESSAGE(message, "E: ", DO_TERMINATE, FALSE, FALSE)

#define Phase(message) QMESSAGE( message, "P: ", FALSE, FALSE, DO_RESINFO)

#define Warning(message) QMESSAGE(message, "W: ", FALSE, FALSE, FALSE)
#define WarningLimit(message,n) QMESSAGE_LIMIT(message, "W: ", n, FALSE, FALSE, FALSE)

#define Info(message) QMESSAGE(message, "I: ", FALSE, FALSE, FALSE)
#define InfoLimit(message,n) QMESSAGE_LIMIT(message, "I: ", n, FALSE, FALSE, FALSE)

#define Debug(message) QMESSAGE(message, "D: ",FALSE, FALSE, FALSE)

#define Stats(message) QMESSAGE(message, "S: ",FALSE, FALSE, FALSE)

#endif
