#ifndef	V_DEBUG_H
#define	V_DEBUG_H

#ifdef	__ICL
/* arguments evaluated in unspecified order */
#pragma warning(disable:981)
#endif

/*
 * Helper macros for output debug and diagnostic messages
 */
#define	STATIC_STRING(identifier,message) \
	static char *identifier = message;

#define	GLOBAL_STRING(identifier,message) \
	char *identifier = message;

#define	EXTERN_STRING(identifier) \
	extern char *identifier;

#ifdef	CHECKED_BUILD

#define DEBUG_MESSAGE(identifier,message) \
	STATIC_STRING(identifier,message)

#define GLOBAL_DEBUG_MESSAGE(identifier,message) \
	GLOBAL_STRING(identifier,message)

#define EXTERN_DEBUG_MESSAGE(identifier) \
	EXTERN_STRING(identifier)

#define CALLER_NAME(name_of_routine) \
	DEBUG_MESSAGE(caller_name,#name_of_routine)

/*
 * Most useful error messages (TAL/emesg.c)
 */
EXTERN_STRING(error_incorrect_parameters)
EXTERN_STRING(error_unable_to_open)
EXTERN_STRING(error_out_of_memory)

/*
 * Macros for printing error messages
 */
#define	ERROR_GENERIC(desc) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s.\n",caller_name,desc);

#define	ERROR_GENERIC_2ARG(desc1,desc2) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s%s.\n",caller_name,desc1,desc2);

#define	ERROR_GENERIC_3ARG(desc1,desc2,desc3) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s%s%s.\n",caller_name,desc1,desc2,desc3);

#define	WARNING_GENERIC(desc) \
	conlPrintf(LOG_WARNING,"%s(): WARNING: %s.\n",caller_name,desc);

#define	WARNING_GENERIC_2ARG(desc1,desc2) \
	conlPrintf(LOG_WARNING,"%s(): WARNING: %s%s.\n",caller_name,desc1,desc2);

#define	WARNING_GENERIC_3ARG(desc1,desc2,desc3) \
	conlPrintf(LOG_WARNING,"%s(): WARNING: %s%s%s.\n",caller_name,desc1,desc2,desc3);

#define	ERROR_INVALID_STR(desc,got_str) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s \"%s\".\n",caller_name,desc,strSafe(got_str));

#define	ERROR_INVALID_INT(desc,got_int) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s \"%d\".\n",caller_name,desc,got_int);

#define	ERROR_INVALID_FLOAT(desc,got_float) \
	conlPrintf(LOG_ERROR,"%s(): ERROR: %s \"%g\".\n",caller_name,desc,got_float);

/*
 * Lexer - related error messages
 */
#define GENERIC_PARSE_ERROR(lexer,desc) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: %s.\n", \
		caller_name,lexSourceName(lexer), \
		lexLastLine(lexer),desc,strSafe(lexLast(lexer)));

#define PARSE_ERROR(lexer,desc) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: %s (got \"%s\").\n", \
		caller_name,lexSourceName(lexer), \
		lexLastLine(lexer),desc,strSafe(lexLast(lexer)));

#define PARSE_ERROR_2ARG(lexer,desc1,desc2) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: %s%s (got \"%s\").\n", \
		caller_name,lexSourceName(lexer), \
		lexLastLine(lexer),desc1,desc2,strSafe(lexLast(lexer)));

#define PARSE_ERROR_3ARG(lexer,desc1,desc2,desc3) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: %s%s%s (got \"%s\").\n", \
		caller_name,lexSourceName(lexer), \
		lexLastLine(lexer),desc1,desc2,desc3,strSafe(lexLast(lexer)));

#define SYN_EXPECTED(lexer,desc) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: expected \"%s\", got \"%s\".\n", \
		caller_name,lexSourceName(lexer), \
		lexLastLine(lexer),desc,strSafe(lexLast(lexer)));

#define SYN_UNEXPECTED(lexer,token) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: unexpected token \"%s\".\n", \
		caller_name,lexSourceName(lexer),lexLastLine(lexer),(token));

#define SYN_UNEXPECTED_EOL(lexer) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: unexpected end of line.\n", \
		caller_name,lexSourceName(lexer),lexLastLine(lexer));

#define SYN_UNEXPECTED_EOF(lexer) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: unexpected end of file.\n", \
		caller_name,lexSourceName(lexer),lexLastLine(lexer));

#define SYN_UNDECLARED(lexer,id) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: \"%s\" undeclared.\n", \
		caller_name,lexSourceName(lexer),lexLastLine(lexer),id);

#define SYN_TYPED_UNDECLARED(lexer,type,id) \
	conlPrintf(LOG_ERROR, \
		"%s(): ERROR in \"%s\", line %u: \"%s %s\" undeclared.\n", \
		caller_name,lexSourceName(lexer),lexLastLine(lexer),type,id);

#else	/* !CHECKED_BUILD */

#define DEBUG_MESSAGE(identifier,message)
#define GLOBAL_DEBUG_MESSAGE(identifier,message)
#define EXTERN_DEBUG_MESSAGE(identifier)
#define CALLER_NAME(name)

#define	ERROR_GENERIC(desc)
#define	ERROR_GENERIC_2ARG(desc1,desc2)
#define	ERROR_GENERIC_3ARG(desc1,desc2,desc3)
#define	WARNING_GENERIC(desc)
#define	WARNING_GENERIC_2ARG(desc1,desc2)
#define	WARNING_GENERIC_3ARG(desc1,desc2,desc3)
#define	ERROR_INVALID_STR(desc,got_str)
#define	ERROR_INVALID_INT(desc,got_int)
#define	ERROR_INVALID_FLOAT(desc,got_float)

#define PARSE_ERROR(lexer,desc)
#define PARSE_ERROR_2ARG(lexer,desc1,desc2)
#define PARSE_ERROR_3ARG(lexer,desc1,desc2,desc3)
#define	SYN_EXPECTED(lexer,desc)
#define SYN_UNEXPECTED_EOL(lexer)
#define SYN_UNEXPECTED_EOF(lexer)
#define SYN_UNDECLARED(lexer,id)
#define SYN_TYPED_UNDECLARED(lexer,id)

#endif	/* !CHECKED_BUILD */

#endif /* !V_DEBUG_H */
