/**
 * Copyright (c) 2018 
 *
 * @file
 * Common Macros and Constants Non Platform Related
 */

#ifndef COMMON_H_
#define COMMON_H_

/* ---------------------------------------------------------------------------
 * Includes
 */
//#include <stdio.h>
#include <stdint.h>
#include <string.h>


#define CLI

/* ---------------------------------------------------------------------------
 * Printing
 */

#define PRINTF(...)            printf(__VA_ARGS__)
#define TRACE_PRINT(...)       printf(__VA_ARGS__)

/* ---------------------------------------------------------------------------
 * Exported Constants
 */

#define PROMPT                      "\n# "
#define SUCCESS                     0
#define ERROR                       1
//#define TRUE                        1
//#define FALSE                       0

/* ---------------------------------------------------------------------------
 * Exported Macros
 */

/* ---------------------------------------------------------------------------
 * Variadic macro argument helpers
 */

/**
 * Expand first argument in variadic list.
 */
#define FIRST(...) FIRST_HELPER(__VA_ARGS__, throwaway)
#define FIRST_HELPER(first, ...) first

/**
 * Expand to "," and subsequent arguments in variadic list if any, else empty.
 *
 * Arbitrary limit of 9 arguments.
 */
#define REST(...) REST_HELPER(NUM(__VA_ARGS__), __VA_ARGS__)
#define REST_HELPER(qty, ...) REST_HELPER2(qty, __VA_ARGS__)
#define REST_HELPER2(qty, ...) REST_HELPER_##qty(__VA_ARGS__)
#define REST_HELPER_ONE(first)
#define REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
#define NUM(...) SELECT_10TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
#define SELECT_10TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10

/**
 * Stringify a token
 *
 * #define foo 4
 * STR(foo) -> "foo"
 */
#define STR(s) #s

/**
 * Expand, then stringify a token
 *
 * #define foo 4
 * XSTR(foo) -> "4"
 */
#define XSTR(s) STR(s)


#define COUNTOF(a)                  (sizeof(a)/sizeof(*(a)))
#define NOOF(a)                     (sizeof(a)/sizeof(a[0]))
#define UNUSED(x)                   (void)x

/** 1st dimension of fixed-size array */
#define ARRAY_DIM(a)                (sizeof(a) / sizeof((a)[0]))

/** Pointer to 1st element of fixed-size array - used to start iterations */
#define ARRAY_START(a)              (&(a)[0])

/** Pointer to last element + 1 of fixed-size array - used to terminate iterations */
#define ARRAY_STOP(a)               (ARRAY_START(a) + ARRAY_DIM(a))

#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
// token pasting madness:
#define COMPILE_TIME_ASSERT3(X,L)   STATIC_ASSERT(X,static_assertion_at_line_##L)
#define COMPILE_TIME_ASSERT2(X,L)   COMPILE_TIME_ASSERT3(X,L)
#define COMPILE_TIME_ASSERT(X)      COMPILE_TIME_ASSERT2(X,__LINE__)

#define LINK_SECTION(name)          __attribute__((section(#name)))

/**
 * Tag a static variable to force compiler not to optimise it away.
 *
 * E.g. a variable in shared ram that is only read.
 *
 * Prefer to "volatile" for this purpose (only) as volatile changes the type.
 */
#define COMPILER_KEEP               __attribute__((__used__))

/**
 * Tag XCP diagnostic variable (read only).
 */
#define XCP_DIAGNOSTIC LINK_SECTION(.xcp.diag)

/**
 * Tag XCP calibration variable (read/write).
 */
#define XCP_CALIBRATION LINK_SECTION(.xcp.cal)


/* ---------------------------------------------------------------------------
 * Exported Types
 */

/* ---------------------------------------------------------------------------
 * Exported Variables
 */

/* ---------------------------------------------------------------------------
 * Exported Functions
 */

#endif /* COMMON_H_ */
