/*
 * Copyright (c) 1996-2007 MIPS Technologies, Inc.
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above
 *      copyright
 *        notice, this list of conditions and the following disclaimer
 *        in the documentation and/or other materials provided with
 *        the distribution.
 *      * Neither the name of MIPS Technologies Inc. nor the names of its
 *        contributors may be used to endorse or promote products derived
 *        from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * stdarg.h : ANSI stdarg definitions
 */


#ifndef __STDARG_H

#ifndef __need___va_list
#define __STDARG_H
#endif
#undef __need___va_list

#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)

/* CPU-independent macros for GNU C 2.96 and above */

#ifndef __VA_LIST
#define __VA_LIST
/* A generally safe declaration for stdio.h, without loading
   everything else and polluting the namespace */
typedef __builtin_va_list __va_list;
#endif

/* Define same as __gnuc_va_list for GNU programs.  */
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
typedef __builtin_va_list __gnuc_va_list;
#endif

/* Define the standard macros for the user,
   if this invocation was from the user program.  */
#ifdef __STDARG_H

#ifdef  __VARARGS_H

/* These macros implement traditional (non-ANSI) varargs
   for GNU C.  */
#define va_alist  __builtin_va_alist

/* ??? We don't process attributes correctly in K&R argument context.  */
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
typedef int __builtin_va_alist_t __attribute__((__mode__(__arg__)));
#elif __mips64 && ! _MIPS_SIM==_ABIO32 && ! __mips_algabi
typedef long long __builtin_va_alist_t;
#else
typedef int __builtin_va_alist_t;
#endif

/* ??? It would be nice to get rid of the ellipsis here.  It causes
   current_function_varargs to be set in cc1.  */
#define va_dcl		__builtin_va_alist_t __builtin_va_alist; ...
#define va_start(v)	__builtin_varargs_start((v))

#else

/* These macros implement ANSI stdarg for GNU C.  */

/* Note that the type used in va_arg is supposed to match the
   actual type **after default promotions**.
   Thus, va_arg (..., short) is not valid.  */
#define va_start(v,l)	__builtin_stdarg_start((v),l)

#endif

/* These macros are common.  */

#define va_end		__builtin_va_end
#define va_arg		__builtin_va_arg
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
#define va_copy(d,s)	__builtin_va_copy((d),(s))
#endif
#define __va_copy(d,s)	__builtin_va_copy((d),(s))

/* Define va_list from __va_list */
typedef __va_list va_list;

#endif /* __STDARG_H */

#else /* __GNUC__ < 2.96 */

#ifndef __VA_LIST
#define __VA_LIST
/* A generally safe declaration for stdio.h, without loading
   everything else and polluting the namespace */
typedef void *__va_list;
#endif

#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
/* For GNU C library */
typedef char *__gnuc_va_list;
#endif

#if !defined(__STDARG_H)
/* dummy only for stdio.h */
#elif	defined(__spur__)
#include "spur/sa-spur.h"
#elif	defined(__MIPSEB__) || defined(__MIPSEL__)
#include "mips/stdarg.h"
#elif	defined(__i860__)
#include "i860/sa-i860.h"
#elif	defined(__pyr__)
#include "pyr/sa-pyr.h"
#elif 	defined(__NeXT__)
#include "NeXT/sa-NeXT.h"
#elif 	defined(__sparc__)
#include "sparc/stdarg.h"
#elif 	defined(__mc68000__) || defined(__i386__) || defined(__ns32000__)
/* standard basic */

typedef char *va_list;

/* Amount of space required in an argument list for an arg of type TYPE.
   TYPE may alternatively be an expression whose type is used.  */

#define __va_rounded_size(TYPE)  \
  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

#ifdef __VARARGS_H
/* old-style, non-ANSI compatibility */
#define va_alist __builtin_va_alist;
#define va_dcl   int __builtin_va_alist; ...

#define va_start(AP) \
  AP = (char *)&__builtin_va_alist;
#else
/* new-style ANSI */
#define va_start(AP, LASTARG) 						\
 (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif

void va_end (va_list);		/* Defined in gnulib ?? */
#define va_end(AP)

#define va_arg(AP, TYPE)						\
 (AP += __va_rounded_size (TYPE),					\
  *((TYPE *) (AP - __va_rounded_size (TYPE))))

#else
#error "stdarg.h"
#endif

#endif /* __GNUC__ >= 2.96 */

#endif /* !defined __STDARG_H */
