// Rowley MSP430 C Compiler
//
// Copyright (c) 2001, 2002 Rowley Associates Limited.
//
// This file may be distributed under the terms of the License Agreement
// provided with this software.
//
// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef __stdarg_H
#define __stdarg_H

// Get definition of __va_list
#include "__crossworks.h"

#ifdef __CROSSWORKS

typedef __va_list va_list;
__va_list __va_base(int);  // intrinsic

#define va_start(ap,parmN) \
((void)((ap) = __va_base(0)))

#define va_arg(ap,type) \
(*(type *)(((ap)=(ap)+sizeof(type))-sizeof(type)))

#define va_copy(dest,src) \
((void)((dest) = (src)))

#define va_end(ap) \
((void)((ap) = (void *)0))

#else

typedef __va_list va_list;

#define va_start(v,l) \
__builtin_va_start((v),l)

#define va_arg \
__builtin_va_arg

#define va_copy(d,s) \
__builtin_va_copy((d),(s))

#define va_end(ap) \
__builtin_va_end(ap)

#endif

#ifdef __CROSSWORKS_DOCUMENTATION

/*! \brief Start access to variable arguments \ingroup Macros \synopsis

\desc \b \this initializes \a ap for subsequent use by the \b va_arg
and \b va_end macros.

The parameter \a parmN is the identifier of the last fixed parameter in
the variable parameter list in the function definition (the one just before
the '\b, ...\b').

The behaviour of \b va_start and \b va_arg is undefined if the parameter
\a parmN is declared with the \b register storage class, with a function
or array type, or with a type that is not compatible with the type that results
after application of the default argument promotions.

\b \this must be invoked before any access to the unnamed arguments.

\b \this and \b va_copy must not be invoked to reinitialize \a ap
without an intervening invocation of the \b va_end macro for the same \a ap.
*/
void va_start( va_list ap, paramN);

/*! \brief Get variable argument value \ingroup Macros \synopsis

\desc \b \this expands to an expression that has the specified type and the
value of the \a type argument. The \a ap parameter must have been initialized
by \b va_start or \b va_copy, without an intervening invocation of \b va_end.
You can create a pointer to a \b va_list and pass that pointer to another
function, in which case the original function may make further use of the original
list after the other function returns.

Each invocation of the \b \this macro modifies \a ap so that the
values of successive arguments are returned in turn. The parameter type must
be a type name such that the type of a pointer to an object that has the specified
type can be obtained simply by postfixing a \b * to \b type.

If there is no actual next argument, or if type is not compatible with the
type of the actual next argument (as promoted according to the default argument
promotions), the behavior of \b va_arg is undefined, except for the following
cases:

\item one type is a signed integer type, the other type is the corresponding unsigned
integer type, and the value is representable in both types;

\item one type is pointer to \b void and the other is a pointer to a character type.

The first invocation of the \b \this macro after that of the \b va_start
macro returns the value of the argument after that specified by \b parmN.
Successive invocations return the values of the remaining arguments in succession.
*/
type va_arg( va_list ap, type);

/*! \brief Finish access to variable arguments \ingroup Macros \synopsis

\desc \b \this indicates a normal return from the function whose variable argument
list \a ap was initialised by \b va_start or \b va_copy. The \b \this
macro may modify \b ap so that it is no longer usable without being reinitialized
by \b va_start or \b va_copy. If there is no corresponding invocation
of \b va_start or \b va_copy, or if \b va_end is not invoked before
the return, the behavior is undefined.
*/
void va_end( va_list ap);

/*! \brief Copy var args \ingroup Macros \synopsis

\desc \b \this initializes \b dest as a copy of \b src, as if the
\b va_start macro had been applied to \b dest followed by the same sequence
of uses of the \b va_arg macro as had previously been used to reach the
present state of \b src. Neither the \b va_copy nor \b va_start
macro shall be invoked to reinitialize \b dest without an intervening invocation
of the \b va_end macro for the same \b dest.
*/
void va_copy( va_list dest, val_list src);

#endif

#endif