shell.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /**
  2. * @file shell.h
  3. * @author Letter (NevermindZZT@gmail.com)
  4. * @brief letter shell
  5. * @version 3.0.0
  6. * @date 2019-12-30
  7. *
  8. * @copyright (c) 2020 Letter
  9. *
  10. */
  11. #ifndef __SHELL_H__
  12. #define __SHELL_H__
  13. #include "shell_cfg.h"
  14. #define SHELL_VERSION "3.2.3" /**< 版本号 */
  15. /**
  16. * @brief shell 断言
  17. *
  18. * @param expr 表达式
  19. * @param action 断言失败操作
  20. */
  21. #define SHELL_ASSERT(expr, action) \
  22. if (!(expr)) { \
  23. action; \
  24. }
  25. #if SHELL_USING_LOCK == 1
  26. #define SHELL_LOCK(shell) shell->lock(shell)
  27. #define SHELL_UNLOCK(shell) shell->unlock(shell)
  28. #else
  29. #define SHELL_LOCK(shell)
  30. #define SHELL_UNLOCK(shell)
  31. #endif /** SHELL_USING_LOCK == 1 */
  32. /**
  33. * @brief shell 命令权限
  34. *
  35. * @param permission 权限级别
  36. */
  37. #define SHELL_CMD_PERMISSION(permission) \
  38. (permission & 0x000000FF)
  39. /**
  40. * @brief shell 命令类型
  41. *
  42. * @param type 类型
  43. */
  44. #define SHELL_CMD_TYPE(type) \
  45. ((type & 0x0000000F) << 8)
  46. /**
  47. * @brief 使能命令在未校验密码的情况下使用
  48. */
  49. #define SHELL_CMD_ENABLE_UNCHECKED \
  50. (1 << 12)
  51. /**
  52. * @brief 禁用返回值打印
  53. */
  54. #define SHELL_CMD_DISABLE_RETURN \
  55. (1 << 13)
  56. /**
  57. * @brief 只读属性(仅对变量生效)
  58. */
  59. #define SHELL_CMD_READ_ONLY \
  60. (1 << 14)
  61. /**
  62. * @brief 命令参数数量
  63. */
  64. #define SHELL_CMD_PARAM_NUM(num) \
  65. ((num & 0x0000000F)) << 16
  66. #ifndef SHELL_SECTION
  67. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  68. #define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
  69. #elif defined (__IAR_SYSTEMS_ICC__)
  70. #define SHELL_SECTION(x) @ x
  71. #elif defined(__GNUC__)
  72. #define SHELL_SECTION(x) __attribute__((section(x), aligned(1)))
  73. #else
  74. #define SHELL_SECTION(x)
  75. #endif
  76. #endif
  77. #ifndef SHELL_USED
  78. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  79. #define SHELL_USED __attribute__((used))
  80. #elif defined (__IAR_SYSTEMS_ICC__)
  81. #define SHELL_USED __root
  82. #elif defined(__GNUC__)
  83. #define SHELL_USED __attribute__((used))
  84. #else
  85. #define SHELL_USED
  86. #endif
  87. #endif
  88. /**
  89. * @brief shell float型参数转换
  90. */
  91. #define SHELL_PARAM_FLOAT(x) (*(float *)(&x))
  92. /**
  93. * @brief shell 代理函数名
  94. */
  95. #define SHELL_AGENCY_FUNC_NAME(_func) agency##_func
  96. /**
  97. * @brief shell代理函数定义
  98. *
  99. * @param _func 被代理的函数
  100. * @param ... 代理参数
  101. */
  102. #define SHELL_AGENCY_FUNC(_func, ...) \
  103. void SHELL_AGENCY_FUNC_NAME(_func)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) \
  104. { _func(__VA_ARGS__); }
  105. #if SHELL_USING_CMD_EXPORT == 1
  106. /**
  107. * @brief shell 命令定义
  108. *
  109. * @param _attr 命令属性
  110. * @param _name 命令名
  111. * @param _func 命令函数
  112. * @param _desc 命令描述
  113. * @param ... 其他参数
  114. */
  115. #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc, ...) \
  116. const char shellCmd##_name[] = #_name; \
  117. const char shellDesc##_name[] = #_desc; \
  118. SHELL_USED const ShellCommand \
  119. shellCommand##_name SHELL_SECTION("shellCommand") = \
  120. { \
  121. .attr.value = _attr, \
  122. .data.cmd.name = shellCmd##_name, \
  123. .data.cmd.function = (int (*)())_func, \
  124. .data.cmd.desc = shellDesc##_name, \
  125. ##__VA_ARGS__ \
  126. }
  127. #if SHELL_USING_FUNC_SIGNATURE == 1
  128. /**
  129. * @brief shell 命令定义
  130. *
  131. * @param _attr 命令属性
  132. * @param _name 命令名
  133. * @param _func 命令函数
  134. * @param _desc 命令描述
  135. * @param _sign 命令签名
  136. */
  137. #define SHELL_EXPORT_CMD_SIGN(_attr, _name, _func, _desc, _sign) \
  138. const char shellCmd##_name[] = #_name; \
  139. const char shellDesc##_name[] = #_desc; \
  140. const char shellSign##_name[] = #_sign; \
  141. SHELL_USED const ShellCommand \
  142. shellCommand##_name SHELL_SECTION("shellCommand") = \
  143. { \
  144. .attr.value = _attr, \
  145. .data.cmd.name = shellCmd##_name, \
  146. .data.cmd.function = (int (*)())_func, \
  147. .data.cmd.desc = shellDesc##_name, \
  148. .data.cmd.signature = shellSign##_name \
  149. }
  150. #endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
  151. /**
  152. * @brief shell 代理命令定义
  153. *
  154. * @param _attr 命令属性
  155. * @param _name 命令名
  156. * @param _func 命令函数
  157. * @param _desc 命令描述
  158. * @param ... 代理参数
  159. */
  160. #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) \
  161. SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \
  162. SHELL_EXPORT_CMD(_attr, _name, SHELL_AGENCY_FUNC_NAME(_func), _desc)
  163. /**
  164. * @brief shell 变量定义
  165. *
  166. * @param _attr 变量属性
  167. * @param _name 变量名
  168. * @param _value 变量值
  169. * @param _desc 变量描述
  170. */
  171. #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
  172. const char shellCmd##_name[] = #_name; \
  173. const char shellDesc##_name[] = #_desc; \
  174. SHELL_USED const ShellCommand \
  175. shellVar##_name SHELL_SECTION("shellCommand") = \
  176. { \
  177. .attr.value = _attr, \
  178. .data.var.name = shellCmd##_name, \
  179. .data.var.value = (void *)_value, \
  180. .data.var.desc = shellDesc##_name \
  181. }
  182. /**
  183. * @brief shell 用户定义
  184. *
  185. * @param _attr 用户属性
  186. * @param _name 用户名
  187. * @param _password 用户密码
  188. * @param _desc 用户描述
  189. */
  190. #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) \
  191. const char shellCmd##_name[] = #_name; \
  192. const char shellPassword##_name[] = #_password; \
  193. const char shellDesc##_name[] = #_desc; \
  194. SHELL_USED const ShellCommand \
  195. shellUser##_name SHELL_SECTION("shellCommand") = \
  196. { \
  197. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
  198. .data.user.name = shellCmd##_name, \
  199. .data.user.password = shellPassword##_name, \
  200. .data.user.desc = shellDesc##_name \
  201. }
  202. /**
  203. * @brief shell 按键定义
  204. *
  205. * @param _attr 按键属性
  206. * @param _value 按键键值
  207. * @param _func 按键函数
  208. * @param _desc 按键描述
  209. */
  210. #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
  211. const char shellDesc##_value[] = #_desc; \
  212. SHELL_USED const ShellCommand \
  213. shellKey##_value SHELL_SECTION("shellCommand") = \
  214. { \
  215. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
  216. .data.key.value = _value, \
  217. .data.key.function = (void (*)(Shell *))_func, \
  218. .data.key.desc = shellDesc##_value \
  219. }
  220. /**
  221. * @brief shell 代理按键定义
  222. *
  223. * @param _attr 按键属性
  224. * @param _value 按键键值
  225. * @param _func 按键函数
  226. * @param _desc 按键描述
  227. * @param ... 代理参数
  228. */
  229. #define SHELL_EXPORT_KEY_AGENCY(_attr, _value, _func, _desc, ...) \
  230. SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \
  231. SHELL_EXPORT_KEY(_attr, _value, SHELL_AGENCY_FUNC_NAME(_func), _desc)
  232. #if SHELL_USING_FUNC_SIGNATURE == 1
  233. /**
  234. * @brief shell 参数解析器定义
  235. *
  236. * @param _attr 参数解析器属性
  237. * @param _type 参数解析器类型
  238. * @param _parser 参数解析器函数
  239. * @param _cleaner 参数清理器
  240. */
  241. #define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner) \
  242. const char shellDesc##_parser[] = #_type; \
  243. SHELL_USED const ShellCommand \
  244. shellCommand##_parser SHELL_SECTION("shellCommand") = \
  245. { \
  246. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
  247. .data.paramParser.type = shellDesc##_parser, \
  248. .data.paramParser.parser = (int (*)(char *, void **))_parser, \
  249. .data.paramParser.cleaner = (int (*)(void *))_cleaner \
  250. }
  251. #endif
  252. #else
  253. /**
  254. * @brief shell 命令item定义
  255. *
  256. * @param _attr 命令属性
  257. * @param _name 命令名
  258. * @param _func 命令函数
  259. * @param _desc 命令描述
  260. */
  261. #define SHELL_CMD_ITEM(_attr, _name, _func, _desc) \
  262. { \
  263. .attr.value = _attr, \
  264. .data.cmd.name = #_name, \
  265. .data.cmd.function = (int (*)())_func, \
  266. .data.cmd.desc = #_desc \
  267. }
  268. /**
  269. * @brief shell 变量item定义
  270. *
  271. * @param _attr 变量属性
  272. * @param _name 变量名
  273. * @param _value 变量值
  274. * @param _desc 变量描述
  275. */
  276. #define SHELL_VAR_ITEM(_attr, _name, _value, _desc) \
  277. { \
  278. .attr.value = _attr, \
  279. .data.var.name = #_name, \
  280. .data.var.value = (void *)_value, \
  281. .data.var.desc = #_desc \
  282. }
  283. /**
  284. * @brief shell 用户item定义
  285. *
  286. * @param _attr 用户属性
  287. * @param _name 用户名
  288. * @param _password 用户密码
  289. * @param _desc 用户描述
  290. */
  291. #define SHELL_USER_ITEM(_attr, _name, _password, _desc) \
  292. { \
  293. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \
  294. .data.user.name = #_name, \
  295. .data.user.password = #_password, \
  296. .data.user.desc = #_desc \
  297. }
  298. /**
  299. * @brief shell 按键item定义
  300. *
  301. * @param _attr 按键属性
  302. * @param _value 按键键值
  303. * @param _func 按键函数
  304. * @param _desc 按键描述
  305. */
  306. #define SHELL_KEY_ITEM(_attr, _value, _func, _desc) \
  307. { \
  308. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
  309. .data.key.value = _value, \
  310. .data.key.function = (void (*)(Shell *))_func, \
  311. .data.key.desc = #_desc \
  312. }
  313. #if SHELL_USING_FUNC_SIGNATURE == 1
  314. /**
  315. * @brief shell 参数解析器item定义
  316. *
  317. * @param _attr 参数解析器属性
  318. * @param _type 参数解析器类型
  319. * @param _parser 参数解析器函数
  320. * @param _cleaner 参数清理器
  321. */
  322. #define SHELL_PARAM_PARSER_ITEM(_attr, _type, _parser, _cleaner) \
  323. { \
  324. .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_PARAM_PARSER), \
  325. .data.paramParser.type = #_type, \
  326. .data.paramParser.parser = (int (*)(char *, void **))_parser, \
  327. .data.paramParser.cleaner = (int (*)(void *))_cleaner \
  328. }
  329. #endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
  330. #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc)
  331. #if SHELL_USING_FUNC_SIGNATURE == 1
  332. #define SHELL_EXPORT_CMD_SIGN(_attr, _name, _func, _desc, _sign)
  333. #endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
  334. #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...)
  335. #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc)
  336. #define SHELL_EXPORT_USER(_attr, _name, _password, _desc)
  337. #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc)
  338. #define SHELL_EXPORT_KEY_AGENCY(_attr, _name, _func, _desc, ...)
  339. #if SHELL_USING_FUNC_SIGNATURE == 1
  340. #define SHELL_EXPORT_PARAM_PARSER(_attr, _type, _parser, _cleaner)
  341. #endif /** SHELL_USING_FUNC_SIGNATURE == 1 */
  342. #endif /** SHELL_USING_CMD_EXPORT == 1 */
  343. /**
  344. * @brief shell command类型
  345. */
  346. typedef enum
  347. {
  348. SHELL_TYPE_CMD_MAIN = 0, /**< main形式命令 */
  349. SHELL_TYPE_CMD_FUNC, /**< C函数形式命令 */
  350. SHELL_TYPE_VAR_INT, /**< int型变量 */
  351. SHELL_TYPE_VAR_SHORT, /**< short型变量 */
  352. SHELL_TYPE_VAR_CHAR, /**< char型变量 */
  353. SHELL_TYPE_VAR_STRING, /**< string型变量 */
  354. SHELL_TYPE_VAR_POINT, /**< 指针型变量 */
  355. SHELL_TYPE_VAR_NODE, /**< 节点变量 */
  356. SHELL_TYPE_USER, /**< 用户 */
  357. SHELL_TYPE_KEY, /**< 按键 */
  358. #if SHELL_USING_FUNC_SIGNATURE == 1
  359. SHELL_TYPE_PARAM_PARSER, /**< 参数解析器 */
  360. #endif
  361. } ShellCommandType;
  362. /**
  363. * @brief Shell定义
  364. */
  365. typedef struct shell_def
  366. {
  367. struct
  368. {
  369. const struct shell_command *user; /**< 当前用户 */
  370. int activeTime; /**< shell激活时间 */
  371. char *path; /**< 当前shell路径 */
  372. #if SHELL_USING_COMPANION == 1
  373. struct shell_companion_object *companions; /**< 伴生对象 */
  374. #endif
  375. #if SHELL_KEEP_RETURN_VALUE == 1
  376. int retVal; /**< 返回值 */
  377. #endif
  378. } info;
  379. struct
  380. {
  381. unsigned short length; /**< 输入数据长度 */
  382. unsigned short cursor; /**< 当前光标位置 */
  383. char *buffer; /**< 输入缓冲 */
  384. char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< 参数 */
  385. unsigned short bufferSize; /**< 输入缓冲大小 */
  386. unsigned short paramCount; /**< 参数数量 */
  387. int keyValue; /**< 输入按键键值 */
  388. } parser;
  389. #if SHELL_HISTORY_MAX_NUMBER > 0
  390. struct
  391. {
  392. char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */
  393. unsigned short number; /**< 历史记录数 */
  394. unsigned short record; /**< 当前记录位置 */
  395. signed short offset; /**< 当前历史记录偏移 */
  396. } history;
  397. #endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
  398. struct
  399. {
  400. void *base; /**< 命令表基址 */
  401. unsigned short count; /**< 命令数量 */
  402. } commandList;
  403. struct
  404. {
  405. unsigned char isChecked : 1; /**< 密码校验通过 */
  406. unsigned char isActive : 1; /**< 当前活动Shell */
  407. unsigned char tabFlag : 1; /**< tab标志 */
  408. } status;
  409. unsigned short (*read)(char *, unsigned short); /**< shell读函数 */
  410. unsigned short (*write)(char *, unsigned short); /**< shell写函数 */
  411. #if SHELL_USING_LOCK == 1
  412. int (*lock)(struct shell_def *); /**< shell 加锁 */
  413. int (*unlock)(struct shell_def *); /**< shell 解锁 */
  414. #endif
  415. } Shell;
  416. /**
  417. * @brief shell command定义
  418. */
  419. typedef struct shell_command
  420. {
  421. union
  422. {
  423. struct
  424. {
  425. unsigned char permission : 8; /**< command权限 */
  426. ShellCommandType type : 4; /**< command类型 */
  427. unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */
  428. unsigned char disableReturn : 1; /**< 禁用返回值输出 */
  429. unsigned char readOnly : 1; /**< 只读 */
  430. unsigned char reserve : 1; /**< 保留 */
  431. unsigned char paramNum : 4; /**< 参数数量 */
  432. } attrs;
  433. int value;
  434. } attr; /**< 属性 */
  435. union
  436. {
  437. struct
  438. {
  439. const char *name; /**< 命令名 */
  440. int (*function)(); /**< 命令执行函数 */
  441. const char *desc; /**< 命令描述 */
  442. #if SHELL_USING_FUNC_SIGNATURE == 1
  443. const char *signature; /**< 函数签名 */
  444. #endif
  445. } cmd; /**< 命令定义 */
  446. struct
  447. {
  448. const char *name; /**< 变量名 */
  449. void *value; /**< 变量值 */
  450. const char *desc; /**< 变量描述 */
  451. } var; /**< 变量定义 */
  452. struct
  453. {
  454. const char *name; /**< 用户名 */
  455. const char *password; /**< 用户密码 */
  456. const char *desc; /**< 用户描述 */
  457. } user; /**< 用户定义 */
  458. struct
  459. {
  460. int value; /**< 按键键值 */
  461. void (*function)(Shell *); /**< 按键执行函数 */
  462. const char *desc; /**< 按键描述 */
  463. } key; /**< 按键定义 */
  464. #if SHELL_USING_FUNC_SIGNATURE == 1
  465. struct
  466. {
  467. const char *type; /**< 参数类型 */
  468. int (*parser)(char *, void **); /**< 解析函数 */
  469. int (*cleaner)(void *); /**< 清理器 */
  470. } paramParser; /**< 参数解析器 */
  471. #endif
  472. } data;
  473. } ShellCommand;
  474. /**
  475. * @brief shell节点变量属性
  476. */
  477. typedef struct
  478. {
  479. void *var; /**< 变量引用 */
  480. int (*get)(); /**< 变量get方法 */
  481. int (*set)(); /**< 变量set方法 */
  482. } ShellNodeVarAttr;
  483. #define shellSetPath(_shell, _path) (_shell)->info.path = _path
  484. #define shellGetPath(_shell) ((_shell)->info.path)
  485. #define shellDeInit(shell) shellRemove(shell)
  486. void shellInit(Shell *shell, char *buffer, unsigned short size);
  487. void shellRemove(Shell *shell);
  488. unsigned short shellWriteString(Shell *shell, const char *string);
  489. void shellPrint(Shell *shell, const char *fmt, ...);
  490. void shellScan(Shell *shell, char *fmt, ...);
  491. Shell* shellGetCurrent(void);
  492. void shellHandler(Shell *shell, char data);
  493. void shellWriteEndLine(Shell *shell, char *buffer, int len);
  494. void shellTask(void *param);
  495. int shellRun(Shell *shell, const char *cmd);
  496. #if SHELL_USING_COMPANION == 1
  497. /**
  498. * @brief shell伴生对象定义
  499. */
  500. typedef struct shell_companion_object
  501. {
  502. int id; /**< 伴生对象ID */
  503. void *obj; /**< 伴生对象 */
  504. struct shell_companion_object *next; /**< 下一个伴生对象 */
  505. } ShellCompanionObj;
  506. signed char shellCompanionAdd(Shell *shell, int id, void *object);
  507. signed char shellCompanionDel(Shell *shell, int id);
  508. void *shellCompanionGet(Shell *shell, int id);
  509. #endif
  510. #endif