]> pd.if.org Git - pdclib/blobdiff - includes/stdarg.h
Re-import from Subversion.
[pdclib] / includes / stdarg.h
index 5d2270535968835b6d685a56cde6011d40adce93..62d0e404e36dbc80d1e0fdfb51e6f7edc04836ff 100644 (file)
@@ -1,32 +1,80 @@
-// ----------------------------------------------------------------------------
-// $Id$
-// ----------------------------------------------------------------------------
-// Public Domain C Library - http://pdclib.sourceforge.net
-// This code is Public Domain. Use, modify, and redistribute at will.
-// ----------------------------------------------------------------------------
-// Variable arguments
-// ----------------------------------------------------------------------------
-
-#ifndef __STDARG_H
-#define __STDARG_H __STDARG_H
-
-// ----------------------------------------------------------------------------
-// TYPEDEFS
-
-typedef do-type va_list; // TODO
-
-// ----------------------------------------------------------------------------
-// MACROS
-
-#define va_arg( va_list ap, Ty )             // TODO
-#define va_copy( va_list dest, va_list src ) // TODO
-#define va_end( va_list ap )                 // TODO
-#define va_start( va_list ap, last-par )     // TODO
-
-/* PDPC code - unreviewed
-#define va_start(ap, parmN) ap = (char *)&parmN + 4
-#define va_arg(ap, type) *(type *)(ap += sizeof(type), ap - sizeof(type))
-#define va_end(ap) ap = 0
-*/
-
-#endif // __STDARG_H
+/* ----------------------------------------------------------------------------
+ * $Id$
+ * ----------------------------------------------------------------------------
+ * Public Domain C Library - http://pdclib.sourceforge.net
+ * This code is Public Domain. Use, modify, and redistribute at will.
+ * ----------------------------------------------------------------------------
+ * Variable arguments
+ * ----------------------------------------------------------------------------
+ * This header is part of a freestanding implementation
+ * --------------------------------------------------------------------------*/
+
+#ifndef _STDARG_H
+#define _STDARG_H _STDARG_H
+
+/* TODO: This code was contributed by Michael Moody, who added:
+ * "As always with my code it's not guaranteed bug-free (In fact I know for a
+ * fact it won't work properly on certain archs)."
+ * Code assumes that:
+ * - arguments are passed on the stack;
+ * - arguments are alligned to pointer size.
+ */
+
+/* ----------------------------------------------------------------------------
+ * TYPEDEFS
+ * --------------------------------------------------------------------------*/
+
+typedef char * va_list;
+
+/* ----------------------------------------------------------------------------
+ * MACROS
+ * --------------------------------------------------------------------------*/
+
+/** Returns the size of 'type' rounded up to the nearest multiple of the size
+ * of a pointer. This macro is just here for clarity.
+ */
+#define __va_round(type)                                                      \
+   (                                                                          \
+      (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1)             \
+   )
+
+/** Initialises ap for use by va_arg by setting ap to point at the first
+ * argument in the ellipsis. parmN is the last known parameter in the function
+ * definition (ie the one before the ellipsis).
+ */
+#define va_start(ap, parmN)                                                   \
+   (                                                                          \
+      (ap) = (char *)&parmN + (__va_round(parmN))                               \
+      ,                                                                       \
+      (void)0                                                                 \
+   )
+
+/** Returns the next argument, assumed variable type is 'type', in the
+ * ellipsis.
+ */
+#define va_arg(ap, type)                                                      \
+   (                                                                          \
+      (ap) += (__va_round(type))                                              \
+      ,                                                                       \
+      (*(type*)((ap) - (__va_round(type))))                                   \
+   )
+
+/** Cleans up ap.
+ */
+#define va_end(ap)                                                            \
+   (                                                                          \
+      (ap) = (void *)0                                                        \
+      ,                                                                       \
+      (void)0                                                                 \
+   )
+
+/** Makes the va_list dest be a copy of the va_list src.
+ */
+#define va_copy(dest, src)                                                    \
+   (                                                                          \
+      (dest) = (src)                                                          \
+      ,                                                                       \
+      (void)0                                                                 \
+   )
+
+#endif /* _STDARG_H */