e40596570afb784542c0b60d8fd96b82d403afb9
[bertos.git] / mware / cmd_hunk.h
1 /**
2  * \file
3  * <!--
4  * Copyright 2004 Giovanni Bajo
5  * Copyright 2004 Develer S.r.l. (http://www.develer.com/)
6  * All Rights Reserved.
7  * -->
8  * This module permits to create hunks for the functions that must be executed through
9  * RPC commands. For instance, given this code:
10  *
11  * \code
12  * ResultCode cmd_add(long a, long b, long* result);
13  * DECLARE_COMMAND_HUNK(add, (long)(long)(NIL), (long)(NIL));
14  * //                        ^ parameters       ^ return values
15  * \endcode
16  *
17  * The macro is expanded to:
18  *
19  * \code
20  * ResultCode cmd_add_hunk(params argv[], params results[])
21  * {
22  *    return cmd_add(argv[0].l, argv[1].l, &results[0].l);
23  * }
24  *
25  * const struct CmdTemplate cmd_add_template = 
26  * {
27  *    "add", "dd", "d", cmd_add_hunk
28  * };
29  * \endcode
30  *
31  * which is all the boilerplate needed to make the function ready for the RPC.
32  * The implementation uses the Boost Preprocessor Library (part of the Boost
33  * library, available at http://www.boost.org). The version we developed the
34  * code with is 1.31.
35  *
36  * \version $Id$
37  *
38  * \author Giovanni Bajo <rasky@develer.com>
39  *
40  * \brief Preprocessor magic to create hunks for the commands executed from the parser
41  *
42  */
43
44 /*#*
45  *#* $Log$
46  *#* Revision 1.2  2006/07/19 12:56:27  bernie
47  *#* Convert to new Doxygen style.
48  *#*
49  *#* Revision 1.1  2006/06/01 12:27:39  marco
50  *#* Added utilities for protocols
51  *#*
52  *#* Revision 1.8  2005/01/12 20:06:31  rasky
53  *#* enum ResultCode è ora un typedef
54  *#*
55  *#* Revision 1.7  2004/12/14 15:10:53  user1
56  *#* Bernardo e Francesco: Assegnazione di un codice di ritorno ai processi
57  *#*
58  *#* Revision 1.6  2004/12/02 17:43:15  rasky
59  *#* Aggiunta la possibilità di settare le flag dei comandi con la nuova macro DECLARE_CMD_HUNK_FLAGS (altrimenti, il default è zero)
60  *#*
61  *#* Revision 1.5  2004/10/16 13:20:15  rasky
62  *#* Aggiunto supporto per alias di uno stesso comando
63  *#*
64  *#* Revision 1.4  2004/08/25 14:17:10  rasky
65  *#* Aggiornato il comment block dei log RCS
66  *#*
67  *#* Revision 1.3  2004/07/31 22:00:07  rasky
68  *#* Fixata una dipendenza
69  *#*
70  *#* Revision 1.2  2004/07/31 14:32:58  rasky
71  *#* args e results possono overlapparsi sempre grazie ai thunk generati: eliminati i due array separati per risparmiare memoria
72  *#*
73  *#* Revision 1.1  2004/05/22 16:29:16  rasky
74  *#* Generazione degli hunk dei comandi RPC tramite preprocessore
75  *#*
76  *#*/
77
78 #ifndef CMD_HUNK_H
79 #define CMD_HUNK_H
80
81 #include "parser.h"
82
83 // Bring in the Boost Preprocess Library
84 #include <boost/preprocessor/library.hpp>
85
86 #define HUNK_INDEX_FOR_NIL      0
87 #define HUNK_INDEX_FOR_string   1
88 #define HUNK_INDEX_FOR_long     2
89 #define HUNK_ARRAY_LETTERS      (3, (NIL, s, l))
90 #define HUNK_ARRAY_STRINGS      (3, ("", "s", "d"))
91
92 // Transform int->l, float->f, etc.
93 #define HUNK_TYPE_LETTER(s, _, type) \
94         BOOST_PP_CAT(HUNK_INDEX_FOR_, type) \
95         /**/
96
97 #define HUNK_TRANSFORMER(_, array, elem) \
98         BOOST_PP_ARRAY_ELEM(elem, array) \
99         /**/
100
101 #define HUNK_SEQ_TRANS_ARRAY(seq, array) \
102         BOOST_PP_SEQ_TRANSFORM(HUNK_TRANSFORMER, array, seq) \
103         /**/
104
105 #define HUNK_PARAM(_, n, seq)    \
106         args_results[n+1]. BOOST_PP_SEQ_ELEM(n, seq) \
107         /**/
108
109 #define HUNK_RESULT(_, n, seq)    \
110         &args_results[n]. BOOST_PP_SEQ_ELEM(n, seq) \
111         /**/
112
113 #define HUNK_IDENTITY(_, dummy, x)  x
114 #define CMD_HUNK_TEMPLATE(func)         cmd_##func###_template
115
116 #define DECLARE_CMD_HUNK_2(func, name, param_types, result_types, flags)    \
117         static ResultCode cmd_##name##_hunk(parms args_results[]) \
118         { \
119                 return cmd_##func( \
120                        BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)),  HUNK_PARAM,  HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_LETTERS)) \
121                        BOOST_PP_COMMA_IF(BOOST_PP_AND(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)), BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)))) \
122                        BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)), HUNK_RESULT, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_LETTERS)) \
123                 ); \
124         } \
125         const struct CmdTemplate CMD_HUNK_TEMPLATE(name) = { \
126                 #name, \
127                 BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_STRINGS)),  \
128                 BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_STRINGS)), \
129                 cmd_##name##_hunk, \
130                 flags \
131         } \
132         /**/
133
134 #define DECLARE_CMD_HUNK(func, param_types, result_types)    \
135         DECLARE_CMD_HUNK_2(func, func, \
136                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
137                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
138                            0) \
139         /**/
140
141 #define DECLARE_CMD_HUNK_NAME(func, name, param_types, result_types)    \
142         DECLARE_CMD_HUNK_2(func, name, \
143                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
144                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
145                            0) \
146         /**/
147
148 #define DECLARE_CMD_HUNK_FLAGS(func, param_types, result_types, flags)    \
149         DECLARE_CMD_HUNK_2(func, func, \
150                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
151                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
152                            flags) \
153         /**/
154
155 #endif