#ifndef basic_HH
#define basic_HH

#define PUBLIC
#define PRIVATE static

/***********************************************************************
     "basic.hh": BASIC functions.
***********************************************************************/

/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: basic.desc,v $
 * Revision 1.2  1993/03/29  18:14:34  lotos
 * keep lint shut down
 *
 * Revision 1.1  1993/03/18  11:14:24  lotos
 * Initial revision
 *
 ***********************************
 $Id: basic.desc,v 1.2 1993/03/29 18:14:34 lotos Exp $
 ***********************************/

/* KJT 29/10/04: changed to use "stdarg" instead of "varargs" */

#include <stdarg.h>

/*
 *** Basic macro definitions ***
 */

/* boolean values */

#ifndef TRUE
#  define TRUE	1
#  define FALSE	0
#endif


/*
 *** LINT passing (complaints suppression) functions ***
 */

/* avoids "lint" complaints about pointer alinment */

#ifndef lint
#  define ALIN(type, ptr)	((type *)(ptr))
#else
#  define ALIN(type, ptr)	((type *)(int)&*(ptr))
#endif

/* useful to avoid "lint" complaints about null effect code */

#ifndef lint
#  define NOOP()	((void)0)
#else
   extern int __NOOP__;

#  define NOOP()	((void)(++__NOOP__))
#endif

/* suppress "lint" complaints about constant conditions */

#ifndef lint
#  define TEST(cond)	(cond)
#else
   extern int __TEST__;

#  define TEST(cond)	(__TEST__= (cond), __TEST__)
#endif

/* avoids "lint" complaints about constants in conditions */

#ifndef lint
#  define EVAL(exp)	(exp)
#else
   extern int __EVAL__;

#  define EVAL(exp)	(__EVAL__? (exp): (exp))
#endif


typedef void (*func_error)();

/*
 *** Error handling functions ***
 */

/* starts an error message (prints an introduction and the header) */

void	start_error (char *head, va_list args);

/* completes an error message (prints the body and appends a NEWLINE) */

void	complete_error (char *body, va_list args);

/* explains an error message (puts the bracketed body in a line) */

void	explain_error (char *body, va_list args);

/* calls an error printing function with varargs argument list */

void	varargs_error (func_error func, char *msg, ...);

/* writes an error message with a NEWLINE appended */

void	error (char *msg, ...);

/* writes an error message and appends a NEWLINE, then exits (code 1) */

void	fail (char *msg, ...);


/*
 *** Programming error detection functions ***
 */

/* if condition is true, writes a message and aborts */

void _cond_error();

#ifndef NDEBUG
#  define abort_if(cond)				\
	  {						\
	    if (TEST(cond))				\
	      _cond_error(__FILE__, __LINE__);		\
	  }
#else
#  define abort_if(cond)	{}
#endif

/* evaluates an expression if condition is true, else aborts */

void _cond_error();

#ifndef NDEBUG
#  define eval_if(cond, exp)				\
	    ((TEST(cond)? NOOP()			\
		    : _cond_error(__FILE__, __LINE__)	\
	     ), (exp))
#else
#  define eval_if(cond, exp)	(exp)
#endif


/*
 *** Memory allocation functions ***
 */

/* allocates typed memory and if cannot, writes a message and exits */

void _alloc_error();

#ifndef lint
#  define _call_malloc(size)	((void *) malloc(size))
#else
   void *_call_malloc();
#endif

#define _talloc(lptr, rptr, nelem)			\
	  (((lptr)= _call_malloc((unsigned)		\
				 sizeof(*(rptr)) *	\
				 (nelem))) == NULL?	\
	     _alloc_error(): NOOP()			\
	  )

#ifndef lint
#  define talloc(ptr, nelem)	_talloc(ptr, ptr, nelem)
#else
#  define talloc(ptr, nelem)	_talloc(ALIN(void, ptr), ptr, nelem)
#endif

/* reallocates typed memory and if cannot, writes a message and exits */

void _alloc_error();

#ifndef lint
#  define _call_realloc(ptr, size) \
	    ((void *) realloc((char *) (ptr), size))
#else
   void *_call_realloc();
#endif

#define _trealloc(lptr, rptr, nelem)			\
	  (((lptr)= _call_realloc(ALIN(void, rptr),	\
				  (unsigned)		\
				  sizeof(*(rptr)) *	\
				  (nelem))) == NULL?	\
	     _alloc_error(): NOOP()			\
	  )

#ifndef lint
#  define trealloc(ptr, nelem)	_trealloc(ptr, ptr, nelem)
#else
#  define trealloc(ptr, nelem)	_trealloc(ALIN(void, ptr), ptr, nelem)
#endif

/* releases a previously allocated typed memory */

#ifndef lint
#  define _call_free(ptr)	((void) free((char *) (ptr)))
#else
   void _call_free();
#endif

#define tfree(ptr)	_call_free(ALIN(void, ptr))
#endif
