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