/*
 * stdarg.h: ANSI draft (X3J11 May 88) library header, section 4.8
 * Copyright (C) Acorn Computers Ltd. 1988
 * version 1.00
 */

#ifndef __stdarg_h
#define __stdarg_h

/*
 * va_list is an array type so that when an object of that type is
 * passed as an argument it gets passed by reference
 * ANSI (2nd public review draft) no longer REQUIRE this, but leave as
 * it is still allowed and must have been put there for some reason.
 *
 * N.B. <stdio.h> is required to declare vfprintf() without defining
 * va_list.  Clearly the type __va_list there must keep in step.
 */
typedef char *va_list;

/*
 * Note that __type is a syntactic item a bit like the type qualifiers
 * 'static', 'register', 'const' etc except that it has no effect!  Its
 * purpose is to indicate when a type is being introduced and thus
 * help (a bit) when the user gets the args to va_arg the wrong way round.
 */
#define __alignof(type) \
   ((char *)&(((struct{char __member1; \
                       ___type type __member2;}*) 0)->__member2) - \
    (char *)0)
#define __alignuptotype(ptr,type) \
   ((char *)((int)(ptr) + (__alignof(type)-1) & ~(__alignof(type)-1)))

#define va_start(ap,parmn) ((void)((ap) = (char *)&(parmn) + sizeof(parmn)))

/*
 * Care is taken in va_arg so that illegal things like va_arg(ap,char)
 * which may seem natural but are illegal are caught.  Note that
 * va_arg(ap,float) is wrong but cannot be patched up at the C macro level.
 */
extern void *__va_illegal_arg(char * /*file*/, int /*line*/);

#define va_arg(ap,type) (sizeof(type) < sizeof(int) ? \
   *(___type type *)__va_illegal_arg(__FILE__,__LINE__) : \
   *(___type type *)(((ap)=__alignuptotype((ap),type)+sizeof(___type type))-\
                     sizeof(___type type)))

/* the next macro is careful to avoid compiler warning messages */
/* and uses a -ve address to ensure address trap                */
#define va_end(ap) ((void)((ap) = (char *)-256))

#endif

/* end of stdarg.h */
