summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Schodet2010-12-15 00:24:38 +0100
committerNicolas Schodet2010-12-15 00:24:38 +0100
commit948c655985dcbe6f8abcc7da850b91e8caa73080 (patch)
treed0d0f3e268b13a62b9c3659d036a56d63c2a86cf
parent00ef637bd3fec023786ec9156664e454be4aab88 (diff)
digital/avr/common: add preprocessor tools
-rw-r--r--digital/avr/common/preproc.h117
-rw-r--r--digital/avr/modules/trace/trace.h21
-rw-r--r--digital/avr/modules/uart/uart_common.h9
3 files changed, 123 insertions, 24 deletions
diff --git a/digital/avr/common/preproc.h b/digital/avr/common/preproc.h
new file mode 100644
index 00000000..a1cebe93
--- /dev/null
+++ b/digital/avr/common/preproc.h
@@ -0,0 +1,117 @@
+#ifndef preproc_h
+#define preproc_h
+/* preproc.h - C preprocessor tools. */
+/* avr.modules - AVR modules. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+/** Define C preprocessor tools to play black magic with the C processor.
+ *
+ * To run tests, give it to cpp -DPREPROC_TEST. */
+
+/** Count the number of macro arguments. */
+#define PREPROC_NARG(args...) \
+ PREPROC_NARG_ (dummy, ## args)
+#define PREPROC_NARG_(dummy_and_args...) \
+ PREPROC_NARG__ (dummy_and_args, \
+ 63, 62, 61, 60, 59, 58, 57, 56, \
+ 55, 54, 53, 52, 51, 50, 49, 48, \
+ 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, \
+ 31, 30, 29, 28, 27, 26, 25, 24, \
+ 23, 22, 21, 20, 19, 18, 17, 16, \
+ 15, 14, 13, 12, 11, 10, 9, 8, \
+ 7, 6, 5, 4, 3, 2, 1, 0)
+#define PREPROC_NARG__(__0, __1, __2, __3, __4, __5, __6, __7, \
+ __8, __9, _10, _11, _12, _13, _14, _15, \
+ _16, _17, _18, _19, _20, _21, _22, _23, \
+ _24, _25, _26, _27, _28, _29, _30, _31, \
+ _32, _33, _34, _35, _36, _37, _38, _39, \
+ _40, _41, _42, _43, _44, _45, _46, _47, \
+ _48, _49, _50, _51, _52, _53, _54, _55, \
+ _56, _57, _58, _59, _60, _61, _62, _63, \
+ N, ...) N
+
+#ifdef PREPROC_TEST
+#define a 1, 2, 3, 4
+NARG:
+ 0: PREPROC_NARG ()
+ 1: PREPROC_NARG (1)
+ 2: PREPROC_NARG (1, 2)
+ 3: PREPROC_NARG (1, 2, 3)
+ 4: PREPROC_NARG (a)
+ 63: PREPROC_NARG (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, \
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
+#endif
+
+/** Paste arguments together. Macro arguments are completely macro-expanded
+ * before they are substituted into a macro body, unless they are stringified
+ * or pasted with other tokens. This macro solves this problem. */
+#define PREPROC_PASTE(args...) \
+ PREPROC_PASTE_2_TOP (PREPROC_PASTE_, PREPROC_NARG (args)) (args)
+
+/* Needed to avoid recursion. */
+#define PREPROC_PASTE_2_TOP(a, b) PREPROC_PASTE_2_TOP_ (a, b)
+#define PREPROC_PASTE_2_TOP_(a, b) a ## b
+/* Need two levels to expand macro used as arguments, see tests. */
+#define PREPROC_PASTE_1(a) a
+#define PREPROC_PASTE_2(a, b) a ## b
+#define PREPROC_PASTE_3(a, b, c) a ## b ## c
+#define PREPROC_PASTE_4(a, b, c, d) a ## b ## c ## d
+#define PREPROC_PASTE_5(a, b, c, d, e) a ## b ## c ## d ## e
+
+#ifdef PREPROC_TEST
+#define a1 1
+#define a2 2
+#define g3 3
+#define WITHOUT_PASTE(x, y) x ## y ## g3
+#define WITH_PASTE(x, y) PREPROC_PASTE (x, y, g3)
+#define WITH_PASTE_EXPANDONCE(x, y) PREPROC_PASTE_3 (x, y, g3)
+PASTE, PASTE_EXPAND:
+Without PASTE, arguments and macros are not expanded:
+ a1a2g3: WITHOUT_PASTE (a1, a2)
+With PASTE, arguments and macros are expanded:
+ 123: WITH_PASTE (a1, a2)
+With only one expansion, arguments are expanded, not macros:
+ 12g3: WITH_PASTE_EXPANDONCE (a1, a2)
+#endif
+
+/** Call a macro whose name is computed by adding the number of arguments.
+ * For example, PREPROC_NARG_CALL(macro_, 1, 2, 3) will expand to macro_3 (1,
+ * 2, 3). */
+#define PREPROC_NARG_CALL(macro_prefix, args...) \
+ PREPROC_PASTE (macro_prefix, PREPROC_NARG (args)) (args)
+
+#ifdef PREPROC_TEST
+#define macro_0() zero
+#define macro_1(a) one which is a
+#define macro_2(a, b) two which are a and b
+#define macro_3(a, b, c) three which are a, b and c
+NARG_CALL:
+ zero: PREPROC_NARG_CALL (macro_)
+ one which is 11: PREPROC_NARG_CALL (macro_, 11)
+ two which are 11 and 22: PREPROC_NARG_CALL (macro_, 11, 22)
+ three which are 11, 22 and 33: PREPROC_NARG_CALL (macro_, 11, 22, 33)
+#endif
+
+#endif /* preproc_h */
diff --git a/digital/avr/modules/trace/trace.h b/digital/avr/modules/trace/trace.h
index 68894059..a8e1e9fc 100644
--- a/digital/avr/modules/trace/trace.h
+++ b/digital/avr/modules/trace/trace.h
@@ -24,33 +24,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
-/**
- * You can find the example on the website :
- * http://gcc.gnu.org/ml/gcc-patches/2000-11/msg00016.html
- */
-#define PASTE_EXPAND(a, b) PASTE(a, b)
-
-#define PASTE(a, b) a ## b
-
-#define TRACE_ARGS_COUNT(...) \
- _TRACE_ARGS_COUNT1 ( , ##__VA_ARGS__)
-
-#define _TRACE_ARGS_COUNT1(...) \
- _TRACE_ARGS_COUNT2 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0)
-
-#define _TRACE_ARGS_COUNT2(_ ,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9, n,...) n
+#include "preproc.h"
#ifndef HOST
#define TRACE(args...) \
- PASTE_EXPAND(TRACE_PRINT, TRACE_ARGS_COUNT(args...)) (args)
+ PREPROC_NARG_CALL(TRACE_PRINT, ## args)
#else /* HOST */
#include <stdio.h>
extern char *trace_table[];
#define TRACE(id, args...) \
do {\
fprintf (stderr, trace_table[id], ## args);\
- PASTE_EXPAND(TRACE_PRINT, TRACE_ARGS_COUNT(id, ## args...))\
- (id, ## args);\
+ PREPROC_NARG_CALL(TRACE_PRINT, id, ## args);\
} while (0)
#endif /* HOST */
diff --git a/digital/avr/modules/uart/uart_common.h b/digital/avr/modules/uart/uart_common.h
index 8f5a3af4..4704f59c 100644
--- a/digital/avr/modules/uart/uart_common.h
+++ b/digital/avr/modules/uart/uart_common.h
@@ -24,19 +24,16 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
+#include "preproc.h"
/* This symbol should be 0 or 1. */
#ifndef UART_N
# error "uart: UART_N missing"
#endif
-/* Utility macros. */
-#define PASTE4_SUB(a, b, c, d) a ## b ## c ## d
-#define PASTE4(a, b, c, d) PASTE4_SUB (a, b, c, d)
-
/* Port selection macros. */
-#define AC_UART(x) PASTE4(AC_UART, UART_N, _, x)
-#define uart(x) PASTE4(uart, UART_N, _, x)
+#define AC_UART(x) PREPROC_PASTE(AC_UART, UART_N, _, x)
+#define uart(x) PREPROC_PASTE(uart, UART_N, _, x)
/* Define uart symbols. */
#define uart_error uart (error)