/* -*- c-file-style: "GNU" -*- */
/*
 * Copyright (C) CNRS, INRIA, Universite Bordeaux 1, Telecom SudParis
 * See COPYING in top-level directory.
 */

#ifndef __EZTRACE_LITL_H__
#define __EZTRACE_LITL_H__

#include "eztrace.h"

#include "litl_read.h"
#include "litl_types.h"
#include "litl_write.h"

#define GET_PARAM(p_ev, num_param) LITL_READ_REGULAR(p_ev)->param[(num_param)]
#define GET_NBPARAMS(p_ev) LITL_READ_REGULAR(p_ev)->nb_params

#define GET_PARAM_RAW(p_ev, ptr) do {					\
    memcpy(ptr, LITL_READ_RAW(p_ev)->data, LITL_READ_RAW(p_ev)->size);	\
 } while(0)

#define CHECK_RETVAL(f) do {						\
    void* retval = NULL;						\
    if(__ezt_trace.status == ezt_trace_status_running ||		\
       __ezt_trace.status == ezt_trace_status_paused ||			\
       __ezt_trace.status == ezt_trace_status_being_finalized) {	\
      retval = f;							\
      if(! retval){							\
	fprintf(stderr, "[EZTrace] The buffer for recording events is full. Stop recording. The trace will be truncated\n");\
	__ezt_trace.status =  ezt_trace_status_stopped;			\
      }									\
    }									\
  } while(0)


#define EZTRACE_EVENT_RAW(code, arg1)			\
  EZTRACE_EVENT_RAW_DATA(code, strlen(arg1) + 1, arg1)

#define EZTRACE_EVENT_RAW_DATA(code, nbytes, arg1)			\
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      litl_write_probe_raw(__ezt_trace.litl_trace, code, nbytes, (litl_data_t *) arg1); \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

/* create an event without any data */
#define EZTRACE_EVENT0_UNPROTECTED(code) CHECK_RETVAL(litl_write_probe_reg_0(__ezt_trace.litl_trace, code))
/* create an event with one value */
#define EZTRACE_EVENT1_UNPROTECTED(code, arg1)				\
  CHECK_RETVAL(litl_write_probe_reg_1(__ezt_trace.litl_trace, code, (litl_param_t)arg1))

/* create an event with two value */
#define EZTRACE_EVENT2_UNPROTECTED(code, arg1, arg2)			\
  CHECK_RETVAL(litl_write_probe_reg_2(__ezt_trace.litl_trace, code, (litl_param_t)arg1, (litl_param_t)arg2))

/* etc. */
#define EZTRACE_EVENT3_UNPROTECTED(code, arg1, arg2, arg3)		\
  CHECK_RETVAL(litl_write_probe_reg_3(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3))

#define EZTRACE_EVENT4_UNPROTECTED(code, arg1, arg2, arg3, arg4)	\
  CHECK_RETVAL(litl_write_probe_reg_4(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4))

#define EZTRACE_EVENT5_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5)	\
  CHECK_RETVAL(litl_write_probe_reg_5(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4, (litl_param_t) arg5))

#define EZTRACE_EVENT6_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6) \
  CHECK_RETVAL(litl_write_probe_reg_6(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4, (litl_param_t) arg5,	\
				      (litl_param_t) arg6))

#define EZTRACE_EVENT7_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
  CHECK_RETVAL(litl_write_probe_reg_7(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4, (litl_param_t) arg5,	\
				      (litl_param_t) arg6, (litl_param_t) arg7))

#define EZTRACE_EVENT8_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
  CHECK_RETVAL(litl_write_probe_reg_8(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4, (litl_param_t) arg5,	\
				      (litl_param_t) arg6, (litl_param_t) arg7,	\
				      (litl_param_t) arg8))

#define EZTRACE_EVENT9_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
  CHECK_RETVAL(litl_write_probe_reg_9(__ezt_trace.litl_trace, code, (litl_param_t) arg1, \
				      (litl_param_t) arg2, (litl_param_t) arg3,	\
				      (litl_param_t) arg4, (litl_param_t) arg5,	\
				      (litl_param_t) arg6, (litl_param_t) arg7,	\
				      (litl_param_t) arg8, (litl_param_t) arg9))


#define EZTRACE_EVENT0(code)			\
  {						\
    EZTRACE_PROTECT {				\
      EZTRACE_PROTECT_ON();			\
	    if (__ezt_trace.status != ezt_trace_status_paused) {	\
      EZTRACE_EVENT0_UNPROTECTED(code);		\
	    } \
      EZTRACE_PROTECT_OFF();			\
    }						\
  }

#define EZTRACE_EVENT1(code, arg1)		\
  {						\
    EZTRACE_PROTECT {				\
      EZTRACE_PROTECT_ON();			\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
	EZTRACE_EVENT1_UNPROTECTED(code, arg1);			\
      }								\
      EZTRACE_PROTECT_OFF();					\
    }						\
  }

#define EZTRACE_EVENT2(code, arg1, arg2)		\
  {							\
    EZTRACE_PROTECT {					\
      EZTRACE_PROTECT_ON();				\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
      EZTRACE_EVENT2_UNPROTECTED(code, arg1, arg2);	\
      } \
      EZTRACE_PROTECT_OFF();				\
    }							\
  }

#define EZTRACE_EVENT3(code, arg1, arg2, arg3)			\
  {								\
    EZTRACE_PROTECT {						\
      EZTRACE_PROTECT_ON();					\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
      EZTRACE_EVENT3_UNPROTECTED(code, arg1, arg2, arg3);	\
      }								\
      EZTRACE_PROTECT_OFF();					\
    }								\
  }

#define EZTRACE_EVENT4(code, arg1, arg2, arg3, arg4)		\
  {								\
    EZTRACE_PROTECT {						\
      EZTRACE_PROTECT_ON();					\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
	EZTRACE_EVENT4_UNPROTECTED(code, arg1, arg2, arg3, arg4);	\
      }									\
      EZTRACE_PROTECT_OFF();					\
    }								\
  }

#define EZTRACE_EVENT5(code, arg1, arg2, arg3, arg4, arg5)		\
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
      EZTRACE_EVENT5_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5);	\
      } \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_EVENT6(code, arg1, arg2, arg3, arg4, arg5, arg6)	\
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      if (__ezt_trace.status != ezt_trace_status_paused) {	\
	EZTRACE_EVENT6_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6); \
      }									\
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_EVENT7(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7)  \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      if (__ezt_trace.status != ezt_trace_status_paused) {		\
      EZTRACE_EVENT7_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
      } \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_EVENT8(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      if (__ezt_trace.status != ezt_trace_status_paused) {		\
      EZTRACE_EVENT8_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);	\
	    } \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_EVENT9(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      if (__ezt_trace.status != ezt_trace_status_paused) {			\
      EZTRACE_EVENT9_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
	    } \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_FORCE_RECORD_EVENT0(code)			\
  {						\
    EZTRACE_PROTECT {				\
      EZTRACE_PROTECT_ON();			\
      EZTRACE_EVENT0_UNPROTECTED(code);		\
      EZTRACE_PROTECT_OFF();			\
    }						\
  }

#define EZTRACE_FORCE_RECORD_EVENT1(code, arg1)		\
  {						\
    EZTRACE_PROTECT {				\
      EZTRACE_PROTECT_ON();			\
      EZTRACE_EVENT1_UNPROTECTED(code, arg1);			\
      EZTRACE_PROTECT_OFF();					\
    }						\
  }

#define EZTRACE_FORCE_RECORD_EVENT2(code, arg1, arg2)		\
  {							\
    EZTRACE_PROTECT {					\
      EZTRACE_PROTECT_ON();				\
      EZTRACE_EVENT2_UNPROTECTED(code, arg1, arg2);	\
      EZTRACE_PROTECT_OFF();				\
    }							\
  }

#define EZTRACE_FORCE_RECORD_EVENT3(code, arg1, arg2, arg3)			\
  {								\
    EZTRACE_PROTECT {						\
      EZTRACE_PROTECT_ON();					\
      EZTRACE_EVENT3_UNPROTECTED(code, arg1, arg2, arg3);	\
      EZTRACE_PROTECT_OFF();					\
    }								\
  }

#define EZTRACE_FORCE_RECORD_EVENT4(code, arg1, arg2, arg3, arg4)		\
  {								\
    EZTRACE_PROTECT {						\
      EZTRACE_PROTECT_ON();					\
      EZTRACE_EVENT4_UNPROTECTED(code, arg1, arg2, arg3, arg4);	\
      EZTRACE_PROTECT_OFF();					\
    }								\
  }

#define EZTRACE_FORCE_RECORD_EVENT5(code, arg1, arg2, arg3, arg4, arg5)		\
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      EZTRACE_EVENT5_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5);	\
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_FORCE_RECORD_EVENT6(code, arg1, arg2, arg3, arg4, arg5, arg6)	\
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      EZTRACE_EVENT6_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6); \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_FORCE_RECORD_EVENT7(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7)  \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      EZTRACE_EVENT7_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_FORCE_RECORD_EVENT8(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      EZTRACE_EVENT8_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);	\
      EZTRACE_PROTECT_OFF();						\
    }									\
  }

#define EZTRACE_FORCE_RECORD_EVENT9(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
  {									\
    EZTRACE_PROTECT {							\
      EZTRACE_PROTECT_ON();						\
      EZTRACE_EVENT9_UNPROTECTED(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
      EZTRACE_PROTECT_OFF();						\
    }									\
  }


#endif	/* __EZTRACE_LITL_H__ */
