1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2010-03-22     Bernard      first version
9  */
10 #ifndef __FINSH_H__
11 #define __FINSH_H__
12 
13 #include <rtdef.h>
14 
15 #ifdef _MSC_VER
16 #pragma section("FSymTab$f",read)
17 #endif /* _MSC_VER */
18 
19 #ifdef FINSH_USING_OPTION_COMPLETION
20 #define FINSH_COND(opt) opt,
21 #else
22 #define FINSH_COND(opt)
23 #endif
24 
25 #ifdef FINSH_USING_DESCRIPTION
26 #define FINSH_DESC(cmd, desc) __fsym_##cmd##_desc,
27 #else
28 #define FINSH_DESC(cmd, desc)
29 #endif
30 
31 typedef long (*syscall_func)(void);
32 #ifdef FINSH_USING_SYMTAB
33 
34 #ifdef __TI_COMPILER_VERSION__
35 #define __TI_FINSH_EXPORT_FUNCTION(f)  PRAGMA(DATA_SECTION(f,"FSymTab"))
36 #endif /* __TI_COMPILER_VERSION__ */
37 
38 /**
39  * @brief Macro to export a command along with its name, description, and options to the symbol table in MSVC.
40  *
41  * @param[in] name The function name associated with the command.
42  * @param[in] cmd The command name.
43  * @param[in] desc The description of the command.
44  * @param[in] opt The options associated with the command, used for option completion.
45  */
46 #ifdef _MSC_VER
47 #define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc, opt)               \
48                 const char __fsym_##cmd##_name[] = #cmd;            \
49                 const char __fsym_##cmd##_desc[] = #desc;           \
50                 __declspec(allocate("FSymTab$f"))                   \
51                 const struct finsh_syscall __fsym_##cmd =           \
52                 {                           \
53                     __fsym_##cmd##_name,    \
54                     FINSH_DESC(cmd, desc)   \
55                     FINSH_COND(opt)         \
56                     (syscall_func)&name     \
57                 };
58 #pragma comment(linker, "/merge:FSymTab=mytext")
59 
60 #elif defined(__TI_COMPILER_VERSION__)
61 #ifdef __TMS320C28XX__
62 #define RT_NOBLOCKED __attribute__((noblocked))
63 #else
64 #define RT_NOBLOCKED
65 #endif
66 #define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc, opt)                           \
67                 __TI_FINSH_EXPORT_FUNCTION(__fsym_##cmd);                       \
68                 const char __fsym_##cmd##_name[] = #cmd;                        \
69                 const char __fsym_##cmd##_desc[] = #desc;                       \
70                 rt_used RT_NOBLOCKED const struct finsh_syscall __fsym_##cmd =  \
71                 {                           \
72                     __fsym_##cmd##_name,    \
73                     FINSH_DESC(cmd, desc)   \
74                     FINSH_COND(opt)         \
75                     (syscall_func)&name     \
76                 };
77 
78 #else
79 #define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc, opt)                                  \
80                 const char __fsym_##cmd##_name[] rt_section(".rodata.name") = #cmd;    \
81                 const char __fsym_##cmd##_desc[] rt_section(".rodata.name") = #desc;   \
82                 rt_used const struct finsh_syscall __fsym_##cmd rt_section("FSymTab")= \
83                 {                           \
84                     __fsym_##cmd##_name,    \
85                     FINSH_DESC(cmd, desc)   \
86                     FINSH_COND(opt)         \
87                     (syscall_func)&name     \
88                 };
89 
90 #endif  /* _MSC_VER */
91 #endif /* FINSH_USING_SYMTAB */
92 
93 /**
94  * @brief Macro definitions to simplify the declaration of exported functions or commands.
95  */
96 #define __MSH_GET_MACRO(_1, _2, _3, _FUN, ...)  _FUN
97 #define __MSH_GET_EXPORT_MACRO(_1, _2, _3, _4, _FUN, ...) _FUN
98 
99 #define _MSH_FUNCTION_CMD2(a0, a1)       \
100         MSH_FUNCTION_EXPORT_CMD(a0, a0, a1, 0)
101 
102 #define _MSH_FUNCTION_CMD2_OPT(a0, a1, a2)       \
103         MSH_FUNCTION_EXPORT_CMD(a0, a0, a1, a0##_msh_options)
104 
105 #define _MSH_FUNCTION_EXPORT_CMD3(a0, a1, a2)       \
106         MSH_FUNCTION_EXPORT_CMD(a0, a1, a2, 0)
107 
108 #define _MSH_FUNCTION_EXPORT_CMD3_OPT(a0, a1, a2, a3)   \
109         MSH_FUNCTION_EXPORT_CMD(a0, a1, a2, a0##_msh_options)
110 
111 
112 /**
113  * @ingroup group_finsh
114  *
115  * @brief This macro exports a system function to finsh shell.
116  *
117  * @param[in] name Name of function.
118  * @param[in] desc Description of function, which will show in help.
119  */
120 #define FINSH_FUNCTION_EXPORT(name, desc)
121 
122 /**
123  * @ingroup group_finsh
124  *
125  * @brief Exports a system function with an alias name to finsh shell.
126  *
127  * @param[in] name Name of function.
128  * @param[in] alias Alias name of function.
129  * @param[in] desc Description of function, which will show in help.
130  */
131 #define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc)
132 
133 /**
134  * @ingroup group_finsh
135  *
136  * @brief Exports a command to module shell.
137  *
138  * @b Parameters
139  *
140  * <tt>[in]</tt> @b command Name of the command.
141  *
142  * <tt>[in]</tt> @b desc    Description of the command, which will show in help list.
143  *
144  * <tt>[in]</tt> @b opt     This is an option, enter any content to enable option completion
145  *
146  * @note This macro can be used in two ways:
147  * @code MSH_CMD_EXPORT(command, desc) @endcode
148  * or
149  * @code MSH_CMD_EXPORT(command, desc, opt) @endcode
150  */
151 #define MSH_CMD_EXPORT(...)                                 \
152     __MSH_GET_MACRO(__VA_ARGS__, _MSH_FUNCTION_CMD2_OPT,    \
153         _MSH_FUNCTION_CMD2)(__VA_ARGS__)
154 
155 /**
156  * @ingroup group_finsh
157  *
158  * @brief Exports a command with alias to module shell.
159  *
160  * @b Parameters
161  *
162  * <tt>[in]</tt> @b command Name of the command.
163  *
164  * <tt>[in]</tt> @b alias   Alias of the command.
165  *
166  * <tt>[in]</tt> @b desc    Description of the command, which will show in help list.
167  *
168  * <tt>[in]</tt> @b opt     An option, enter any content to enable option completion.
169  *
170  * @note This macro can be used in two ways:
171  * @code #define MSH_CMD_EXPORT_ALIAS(command, alias, desc) @endcode
172  * or
173  * @code #define MSH_CMD_EXPORT_ALIAS(command, alias, desc, opt) @endcode
174  */
175 #define MSH_CMD_EXPORT_ALIAS(...)                                           \
176     __MSH_GET_EXPORT_MACRO(__VA_ARGS__, _MSH_FUNCTION_EXPORT_CMD3_OPT,      \
177             _MSH_FUNCTION_EXPORT_CMD3)(__VA_ARGS__)
178 
179 /* system call table */
180 struct finsh_syscall
181 {
182     const char     *name;       /* the name of system call */
183 #if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
184     const char     *desc;       /* description of system call */
185 #endif
186 
187 #ifdef FINSH_USING_OPTION_COMPLETION
188     struct msh_cmd_opt *opt;
189 #endif
190     syscall_func func;      /* the function address of system call */
191 };
192 
193 /* system call item */
194 struct finsh_syscall_item
195 {
196     struct finsh_syscall_item *next;    /* next item */
197     struct finsh_syscall syscall;       /* syscall */
198 };
199 
200 #ifdef FINSH_USING_OPTION_COMPLETION
201 typedef struct msh_cmd_opt
202 {
203     rt_uint32_t     id;
204     const char      *name;
205     const char      *des;
206 } msh_cmd_opt_t;
207 
208 /* Command options declaration and definition macros */
209 
210 /**
211  * @brief Declares a static array of command options for a specific command.
212  *
213  * @param[in] command The command associated with these options.
214  */
215 #ifdef _MSC_VER
216 #define CMD_OPTIONS_STATEMENT(command) static struct msh_cmd_opt command##_msh_options[16];
217 #else
218 #define CMD_OPTIONS_STATEMENT(command) static struct msh_cmd_opt command##_msh_options[];
219 #endif
220 
221 /**
222  * @brief Starts the definition of command options for a specific command.
223  *
224  * @param[in] command The command these options are associated with.
225  */
226 #ifdef _MSC_VER
227 #define CMD_OPTIONS_NODE_START(command) static struct msh_cmd_opt command##_msh_options[16] = {
228 #else
229 #define CMD_OPTIONS_NODE_START(command) static struct msh_cmd_opt command##_msh_options[] = {
230 #endif
231 
232 /**
233  * @brief Defines a single command option.
234  *
235  * @param[in] _id Unique identifier for the option.
236  * @param[in] _name The name of the option.
237  * @param[in] _des Description of the option.
238  */
239 #define CMD_OPTIONS_NODE(_id, _name, _des) {.id = _id, .name = #_name, .des = #_des},
240 
241 /**
242  * Marks the end of command options definition.
243  */
244 #define CMD_OPTIONS_NODE_END    {0},};
245 
246 void msh_opt_list_dump(void *options);
247 int msh_cmd_opt_id_get(int argc, char *argv[], void *options);
248 #define MSH_OPT_ID_GET(fun) msh_cmd_opt_id_get(argc, argv, (void*) fun##_msh_options)
249 #define MSH_OPT_DUMP(fun)   msh_opt_list_dump((void*) fun##_msh_options)
250 
251 #else
252 #define CMD_OPTIONS_STATEMENT(command)
253 #define CMD_OPTIONS_NODE_START(command)
254 #define CMD_OPTIONS_NODE(_id, _name, _des)
255 #define CMD_OPTIONS_NODE_END
256 #define MSH_OPT_ID_GET(fun) ((int)(-1UL))
257 #define MSH_OPT_DUMP(fun)   do{}while(0)
258 #endif
259 
260 extern struct finsh_syscall_item *global_syscall_list;
261 extern struct finsh_syscall *_syscall_table_begin, *_syscall_table_end;
262 
263 #if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
264     struct finsh_syscall *finsh_syscall_next(struct finsh_syscall *call);
265     #define FINSH_NEXT_SYSCALL(index)  index=finsh_syscall_next(index)
266 #else
267     #define FINSH_NEXT_SYSCALL(index)  index++
268 #endif
269 
270 #if !defined(RT_USING_POSIX_STDIO) && defined(RT_USING_DEVICE)
271 void finsh_set_device(const char *device_name);
272 #endif
273 
274 #endif
275