Rename myself
[bertos.git] / bertos / mware / cmd_hunk.h
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2004 Giovanni Bajo
30  * Copyright 2004 Develer S.r.l. (http://www.develer.com/)
31  * All Rights Reserved.
32  * -->
33  *
34  * \brief Preprocessor magic to create hunks for the commands executed from the parser
35  *
36  * This module permits to create hunks for the functions that must be executed through
37  * RPC commands. For instance, given this code:
38  *
39  * \code
40  * ResultCode cmd_add(long a, long b, long* result);
41  * DECLARE_COMMAND_HUNK(add, (long)(long)(NIL), (long)(NIL));
42  * //                        ^ parameters       ^ return values
43  * \endcode
44  *
45  * The macro is expanded to:
46  *
47  * \code
48  * ResultCode cmd_add_hunk(params argv[], params results[])
49  * {
50  *    return cmd_add(argv[0].l, argv[1].l, &results[0].l);
51  * }
52  *
53  * const struct CmdTemplate cmd_add_template = 
54  * {
55  *    "add", "dd", "d", cmd_add_hunk
56  * };
57  * \endcode
58  *
59  * which is all the boilerplate needed to make the function ready for the RPC.
60  * The implementation uses the Boost Preprocessor Library (part of the Boost
61  * library, available at http://www.boost.org). The version we developed the
62  * code with is 1.31.
63  *
64  * \version $Id$
65  *
66  * \author Giovanni Bajo <rasky@develer.com>
67  *
68  */
69
70 #ifndef CMD_HUNK_H
71 #define CMD_HUNK_H
72
73 #include "parser.h"
74
75 // Bring in the Boost Preprocess Library
76 #include <boost/preprocessor/library.hpp>
77
78 #define HUNK_INDEX_FOR_NIL      0
79 #define HUNK_INDEX_FOR_string   1
80 #define HUNK_INDEX_FOR_long     2
81 #define HUNK_ARRAY_LETTERS      (3, (NIL, s, l))
82 #define HUNK_ARRAY_STRINGS      (3, ("", "s", "d"))
83
84 // Transform int->l, float->f, etc.
85 #define HUNK_TYPE_LETTER(s, _, type) \
86         BOOST_PP_CAT(HUNK_INDEX_FOR_, type) \
87         /**/
88
89 #define HUNK_TRANSFORMER(_, array, elem) \
90         BOOST_PP_ARRAY_ELEM(elem, array) \
91         /**/
92
93 #define HUNK_SEQ_TRANS_ARRAY(seq, array) \
94         BOOST_PP_SEQ_TRANSFORM(HUNK_TRANSFORMER, array, seq) \
95         /**/
96
97 #define HUNK_PARAM(_, n, seq)    \
98         args_results[n+1]. BOOST_PP_SEQ_ELEM(n, seq) \
99         /**/
100
101 #define HUNK_RESULT(_, n, seq)    \
102         &args_results[n]. BOOST_PP_SEQ_ELEM(n, seq) \
103         /**/
104
105 #define HUNK_IDENTITY(_, dummy, x)  x
106 #define CMD_HUNK_TEMPLATE(func)         cmd_##func###_template
107
108 #define DECLARE_CMD_HUNK_2(func, name, param_types, result_types, flags)    \
109         static ResultCode cmd_##name##_hunk(parms args_results[]) \
110         { \
111                 return cmd_##func( \
112                        BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)),  HUNK_PARAM,  HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_LETTERS)) \
113                        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)))) \
114                        BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)), HUNK_RESULT, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_LETTERS)) \
115                 ); \
116         } \
117         const struct CmdTemplate CMD_HUNK_TEMPLATE(name) = { \
118                 #name, \
119                 BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_STRINGS)),  \
120                 BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_STRINGS)), \
121                 cmd_##name##_hunk, \
122                 flags \
123         } \
124         /**/
125
126 #define DECLARE_CMD_HUNK(func, param_types, result_types)    \
127         DECLARE_CMD_HUNK_2(func, func, \
128                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
129                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
130                            0) \
131         /**/
132
133 #define DECLARE_CMD_HUNK_NAME(func, name, param_types, result_types)    \
134         DECLARE_CMD_HUNK_2(func, name, \
135                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
136                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
137                            0) \
138         /**/
139
140 #define DECLARE_CMD_HUNK_FLAGS(func, param_types, result_types, flags)    \
141         DECLARE_CMD_HUNK_2(func, func, \
142                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \
143                            BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \
144                            flags) \
145         /**/
146
147 #endif