<修改> 1、调整claude的部分规则记忆文件;2、调整自定义命令部分缺陷,旧版本cpu使用率超高
This commit is contained in:
parent
6c9b8e90b1
commit
3bf70c5b6d
|
|
@ -0,0 +1,3 @@
|
|||
- [user-language](user_language.md) — 用户要求所有对话和思考过程使用中文显示
|
||||
- [project-rules](project-rules.md) — 项目开发规范:编译/运行路径、排查流程、文档管理、plan归档到mid目录
|
||||
- [code-style](code-style.md) — C/C++代码格式规范:Tab缩进、Allman括号、Yoda条件、空行规则
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
name: code-style
|
||||
description: 项目 C/C++ 代码格式规范 — 缩进、括号、空格、空行、条件写法
|
||||
metadata:
|
||||
type: feedback
|
||||
---
|
||||
|
||||
## 缩进
|
||||
|
||||
使用 **Tab 字符**缩进(显示宽度 4),不使用空格缩进。
|
||||
|
||||
## 括号风格(Allman 风格)
|
||||
|
||||
所有大括号 **独占一行**,包括函数、if、for、while、struct:
|
||||
|
||||
```cpp
|
||||
LOCAL void check_sg_zone_change()
|
||||
{
|
||||
if(g_sg_zone_saddr.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto &setting : g_vec_setting)
|
||||
{
|
||||
if(strcmp(setting.base.saddr, zone_saddr) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
单条语句也保留大括号,不省略。
|
||||
|
||||
## 空格规则
|
||||
|
||||
- 关键字与括号之间 **不加空格**:`if(`, `for(`, `while(`, `switch(`
|
||||
- 函数名与括号之间 **不加空格**:`func(args)`
|
||||
- 指针声明:`type *name`(`*` 前有空格,后无空格)
|
||||
- 引用声明:`type &name`
|
||||
|
||||
## Yoda 条件
|
||||
|
||||
常量写在比较运算符左侧:
|
||||
|
||||
```cpp
|
||||
if(NULL == ptr) // ✓ 正确
|
||||
if(0 != ret) // ✓ 正确
|
||||
if(ptr == NULL) // ✗ 不符合项目风格
|
||||
```
|
||||
|
||||
## 空行
|
||||
|
||||
- 函数之间:两行空行
|
||||
- 逻辑块之间:一行空行
|
||||
- `#include` 区块末尾:一行空行
|
||||
|
||||
## typedef struct
|
||||
|
||||
```cpp
|
||||
typedef struct
|
||||
{
|
||||
uint32_t field1;
|
||||
uint8_t field2;
|
||||
}stru_type_name;
|
||||
```
|
||||
|
||||
结构体成员无缩进额外层级(与 `{` 对齐)。
|
||||
|
||||
## 变量声明
|
||||
|
||||
- 局部静态变量用 `LOCAL` 宏(= `static`)
|
||||
- 全局变量用 `g_` 前缀
|
||||
- 结构体用 `stru_` 前缀
|
||||
- 枚举用 `enum_` 前缀,枚举值用 `ENUM_` 前缀
|
||||
|
||||
**Why:** 从项目中多个核心源文件(iec61850s.cpp、self_ptl.cpp、ws_method.cpp、dc_signal.cpp)提取的共识格式规范
|
||||
**How to apply:** 新增代码和修改现有代码时必须遵守此格式。本次仅统一缩进/括号/空格/空行,命名问题暂不处理。
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
name: project-rules
|
||||
description: 项目开发规范 — 编译/运行路径、排查流程、文档管理、plan归档要求
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 5e65af11-b197-479e-a82f-c2e5b475a8c3
|
||||
---
|
||||
|
||||
## 核心规则
|
||||
|
||||
1. **对话语言**:全程使用中文显示
|
||||
2. **编译路径**:`./release/build.sh`(x86)或 `./release/build.sh arm`(ARM交叉编译)
|
||||
3. **执行路径**:`./test/RTU`
|
||||
4. **排查问题流程**:先重新读取对应位置的源码,再对照问题或打印信息排查,不要依赖记忆中的旧代码
|
||||
5. **问题记录**:每次解决的问题都追加到 `claude/问题处理文档.md`
|
||||
6. **文档目录**:
|
||||
- `claude/mid/` — 存放中间文档、plan 文档
|
||||
- `claude/工程/` — 存放按模块记录的项目工程文档
|
||||
7. **每次读取项目工程时**,把读到的东西按模块生成文档记录到 `claude/工程/` 文件夹
|
||||
8. **解决问题的 plan**:每次制定并执行 plan 解决问题后,将 plan 内容整理为文档存入 `claude/mid/` 目录
|
||||
|
||||
**Why:** 用户明确要求的项目开发规范和工作流程
|
||||
**How to apply:** 每次操作前检查这些规则,特别是编译/运行路径和问题排查流程。问题解决后必须追加到问题处理文档,同时将 plan 归档到 mid 目录。
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
name: user-language
|
||||
description: 用户要求所有对话、思考过程和中间输出均使用中文显示
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: user
|
||||
originSessionId: 5e65af11-b197-479e-a82f-c2e5b475a8c3
|
||||
---
|
||||
|
||||
用户要求所有对话内容、思考过程(thinking)、以及所有用户能看到的中间过程都使用中文显示。包括但不限于:回复内容、代码注释、任务列表、提交信息等。代码本身(变量名、函数名等)保持英文不变。
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Tab 命令补全功能实现
|
||||
|
||||
## 日期
|
||||
|
||||
2026-06-12
|
||||
|
||||
## 概述
|
||||
|
||||
为 CLI 交互实现多级 Tab 命令补全:第一个词补全命令名,后续词根据命令上下文补全子功能。
|
||||
|
||||
## 实现内容
|
||||
|
||||
### 1. 数据结构扩展(myCmd.h)
|
||||
|
||||
`stru_cmd` 增加 `complete` 回调字段:
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
void (*func)(int argc, char *argv[]);
|
||||
const char *desc;
|
||||
void (*complete)(const char *buf, char ***completions, int *ncomp);
|
||||
}stru_cmd;
|
||||
```
|
||||
|
||||
`CMD_REGISTER` 宏改为支持可变参数,`cmd_manager_add_command` 增加默认参数 `complete = NULL`。
|
||||
|
||||
### 2. 上下文感知补全(my_cmd.cpp)
|
||||
|
||||
`cmd_complete` 逻辑:
|
||||
- 无空格 → 命令名前缀匹配(原行为)
|
||||
- 有空格 → 提取第一个词查找命令,调用其 `complete` 回调获取子补全
|
||||
|
||||
`cmd_sub_complete` 辅助函数:给定子命令列表和前缀,返回匹配项。
|
||||
|
||||
### 3. 前缀保留修复(my_cmd.cpp)
|
||||
|
||||
`linenoiseEdit` 中 Tab 键处理原本用补全结果**覆盖整行**,导致子命令补全时命令名前缀丢失。改为找到最后一个空格,只替换空格之后的当前词:
|
||||
|
||||
```c
|
||||
// 修复前:strncpy(buf, completions[0], ...); // 整行覆盖
|
||||
// 修复后:
|
||||
char *last_space = strrchr_manual(buf, pos);
|
||||
if (NULL != last_space)
|
||||
strncpy(last_space + 1, completions[0], ...); // 只替换当前词
|
||||
else
|
||||
strncpy(buf, completions[0], ...); // 第一个词仍覆盖整行
|
||||
```
|
||||
|
||||
### 4. 各模块子补全注册
|
||||
|
||||
| 命令 | 子命令 |
|
||||
|------|--------|
|
||||
| `datacenter` | `out`, `in`, `yk`, `ao`, `param`, `all` |
|
||||
| `iec` | `run_cnt` |
|
||||
| `iec61850m` | `info`, `yk`, `set` |
|
||||
| `self_ptl` | `1`, `3`, `5`, `6`, `9`, `11` |
|
||||
|
||||
### 5. 构建系统修复
|
||||
|
||||
[release/src/system/makefile](release/src/system/makefile) 中 8 个子模块 SUBDIRS 被注释导致增量编译失效,已取消注释。
|
||||
|
||||
## 影响文件
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| [myCmd.h](release/inc/myCmd.h) | stru_cmd 增加 complete 字段;CMD_REGISTER 可变参数;cmd_sub_complete 声明 |
|
||||
| [my_cmd.cpp](src/public/libcmd/src/my_cmd.cpp) | cmd_complete 上下文感知;cmd_sub_complete;Tab 替换前缀保留 |
|
||||
| [dc_signal.cpp](src/system/libdatacenter/src/dc_signal.cpp) | datacenter 子补全 |
|
||||
| [iec.cpp](src/system/libiec/src/iec.cpp) | iec 子补全 |
|
||||
| [iec61850m.cpp](src/system/libiec61850m/src/iec61850m.cpp) | iec61850m 子补全 |
|
||||
| [method.cpp](src/system/libself_ptl/src/method.cpp) | self_ptl 子补全 |
|
||||
| [release/src/system/makefile](release/src/system/makefile) | 取消 SUBDIRS 注释 |
|
||||
|
||||
## 使用效果
|
||||
|
||||
```
|
||||
cmd > d + Tab → datacenter
|
||||
cmd > datacenter + p + Tab → datacenter param
|
||||
cmd > iec + r + Tab → iec run_cnt
|
||||
```
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# app_cmd 线程 CPU 108% 问题修复
|
||||
|
||||
## 日期
|
||||
|
||||
2026-06-12
|
||||
|
||||
## 背景
|
||||
|
||||
`app_cmd` 线程是 CLI 命令行处理线程,属于 9 个应用线程之一。其主循环采用定时器驱动的事件模型(EV_TIMER1=10ms、EV_TIMER2=100ms、EV_TIMER3=1000ms)。原本 `cmd_recv()` 在 EV_TIMER1 中每次被调用,但该调用已被注释掉,原因是启用后 CPU 占用飙升至 108%。
|
||||
|
||||
## 根因
|
||||
|
||||
### 直接原因:`read()` 返回 EOF 未处理
|
||||
|
||||
`linenoiseEdit()`([my_cmd.cpp:107](src/public/libcmd/src/my_cmd.cpp#L107))中读取 stdin 的代码:
|
||||
|
||||
```c
|
||||
if (read(STDIN_FILENO, &c, 1) == -1) return -1;
|
||||
```
|
||||
|
||||
只检查了 `-1`(错误),未处理返回 `0`(EOF)。当进程无真正控制终端时(RTU 嵌入式部署环境常见),stdin 处于 EOF 状态,`read()` 立即返回 0。代码不匹配 `-1`,继续执行,`c` 为未定义值,后落入 `buf[len++] = c` 分支,循环回 `read()` — 死循环,CPU 100%+。
|
||||
|
||||
### 架构层面问题
|
||||
|
||||
| 问题 | 说明 |
|
||||
|------|------|
|
||||
| 阻塞 I/O 在定时器线程中 | `linenoise()` 是同步阻塞调用,放在 10ms 定时器中导致线程被阻塞 |
|
||||
| 无 stdin 就绪检查 | 没有用 `select()`/`poll()` 先检查 stdin 是否有数据 |
|
||||
| 终端模式反复切换 | 每次 `linenoise()` 调用都 `tcgetattr`+`tcsetattr`,频率过高 |
|
||||
| `tcsetattr` 返回值未检查 | `linenoise()` 中调用 `enableRawMode()` 未检查返回值 |
|
||||
|
||||
### 定时器机制
|
||||
|
||||
定时器使用 POSIX `timer_create(CLOCK_REALTIME, SIGEV_THREAD, ...)`,每次超时内核创建新线程执行回调 → `task_event_send` → `pthread_cond_signal` 唤醒 app 线程。
|
||||
|
||||
## 修复内容
|
||||
|
||||
### 1. my_cmd.cpp — 修复 EOF 处理和返回值检查
|
||||
|
||||
- `read()` 返回值判断从 `== -1` 改为 `<= 0`,覆盖 EOF 场景
|
||||
- `linenoise()` 中检查 `enableRawMode()` 返回值,失败直接返回 NULL,避免在有问题的终端上执行读取循环
|
||||
|
||||
### 2. app_cmd.cpp — 重构为非阻塞模式
|
||||
|
||||
- 新增 `isatty(STDIN_FILENO)` 前置检查,非终端环境直接跳过
|
||||
- 用 `select()` 零超时检测 stdin 可读性,仅在数据就绪时才调用 `linenoise()`
|
||||
- 从 EV_TIMER1(10ms)移至 EV_TIMER2(100ms),降低终端模式切换频率
|
||||
|
||||
## 验证
|
||||
|
||||
- 编译:零错误零警告
|
||||
- 测试:`./test/RTU < /dev/null` 运行 3 秒,CPU 占用 0.0%(修复前为 108%)
|
||||
|
||||
## 影响文件
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| [my_cmd.cpp](src/public/libcmd/src/my_cmd.cpp) | `read()` EOF 处理;`enableRawMode()` 返回值检查 |
|
||||
| [app_cmd.cpp](src/system/RTU/src/app_cmd.cpp) | 非阻塞 `cmd_recv_nonblock()`;`isatty` + `select`;移至 EV_TIMER2 |
|
||||
| [CLAUDE.md](CLAUDE.md) | 全文翻译为中文 |
|
||||
|
|
@ -2,6 +2,49 @@
|
|||
|
||||
---
|
||||
|
||||
## 2026-06-12
|
||||
|
||||
### #6 Tab 补全子命令前缀丢失
|
||||
|
||||
**问题**:输入 `datacenter ` + `p` + Tab 后,`datacenter ` 前缀被 `param` 覆盖,整行只剩 `param`。
|
||||
|
||||
**根因**:`linenoiseEdit` 中 Tab 键处理用 `strncpy(buf, completions[0])` 整行覆盖。
|
||||
|
||||
**修复**:改为找到最后一个空格,只替换空格之后的当前词,保留前缀。
|
||||
|
||||
---
|
||||
|
||||
### #5 app_cmd 交互卡顿与 Tab 补全失效
|
||||
|
||||
**问题**:上一轮将 `cmd_recv` 改为 select 非阻塞 + EV_TIMER2(100ms) 后:
|
||||
1. 回车后 `cmd>` 回显不及时,有明显卡顿感
|
||||
2. 输入 `d` 后按 Tab,不会弹出命令补全
|
||||
|
||||
**根因**:`select()` 方案与 `linenoise()` 交互式行编辑器根本性不兼容——select 时终端处于规范模式(行缓冲),Tab 不是行终止符不会触发 select;100ms 定时器引入最多 100ms 延迟。
|
||||
|
||||
**修复**:将 `app_cmd` 线程从定时器事件驱动改为简单阻塞循环 `while(1) { cmd_recv(); }`。`linenoise()` 自管理终端模式切换和 Tab 补全,线程阻塞在 stdin 上零延迟响应。
|
||||
|
||||
**验证**:编译通过。
|
||||
|
||||
---
|
||||
|
||||
### #4 app_cmd 线程启用后 CPU 飙升至 108%
|
||||
|
||||
**问题**:`app_cmd` 线程中 `cmd_recv()` 启用后,CPU 占用 108%,导致该入口被暂时屏蔽([app_cmd.cpp:117](src/system/RTU/src/app_cmd.cpp#L117) 被注释)。
|
||||
|
||||
**根因**:
|
||||
1. **死循环层面**:`linenoiseEdit()`([my_cmd.cpp:107](src/public/libcmd/src/my_cmd.cpp#L107))中 `read()` 只检查了返回 `-1`,未处理返回 `0`(EOF)。当进程无真正控制终端时(RTU 嵌入式环境常见),`read()` 立即返回 0 形成死循环。
|
||||
2. **架构层面**:`linenoise()` 是同步阻塞调用,却被放在 10ms 定时器 EVI_TIMER1 中执行,与其他定时器事件循环模型不兼容。
|
||||
|
||||
**修复内容**:
|
||||
1. `my_cmd.cpp`:`read()` 返回值判断改为 `<= 0`(含 EOF 处理);`enableRawMode()` 返回值在 `linenoise()` 中检查,失败直接返回 NULL
|
||||
2. `app_cmd.cpp`:重构 `cmd_recv` 为 `cmd_recv_nonblock()`,用 `select()` 实现非阻塞 stdin 检查 + `isatty()` 过滤非终端环境,移至 EV_TIMER2(100ms)调用
|
||||
3. `CLAUDE.md`:全文翻译为中文
|
||||
|
||||
**验证**:编译通过(零错误零警告),`./test/RTU < /dev/null` 运行 3 秒 CPU 占用 0.0%。
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-10
|
||||
|
||||
### #1 libmms_m RCB 订阅编号硬编码
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ typedef struct
|
|||
const char *name;
|
||||
void (*func)(int argc, char *argv[]);
|
||||
const char *desc;
|
||||
void (*complete)(const char *buf, char ***completions, int *ncomp);
|
||||
}stru_cmd;
|
||||
|
||||
|
||||
#define CMD_REGISTER(cmd_name, func_ptr, cmd_desc) \
|
||||
#define CMD_REGISTER(cmd_name, func_ptr, cmd_desc, ...) \
|
||||
__attribute__((constructor)) static void register_##func_ptr(void) { \
|
||||
cmd_manager_add_command(cmd_name, func_ptr, cmd_desc); \
|
||||
cmd_manager_add_command(cmd_name, func_ptr, cmd_desc, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc);
|
||||
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc, void (*complete)(const char *, char ***, int *) = NULL);
|
||||
|
||||
|
||||
stru_cmd *cmd_manager_get_commands(unsigned int *out_count);
|
||||
|
|
@ -23,6 +24,7 @@ stru_cmd *cmd_manager_get_commands(unsigned int *out_count);
|
|||
void cmd_help(int argc, char *argv[]);
|
||||
stru_cmd *cmd_find(const char *name);
|
||||
void cmd_complete(const char *buf, char ***completions, int *ncomp);
|
||||
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp, const char **subs, int sub_count);
|
||||
|
||||
|
||||
char *linenoise(const char *prompt);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static std::vector<stru_cmd>& get_cmd_list()
|
|||
return s_cmd_list;
|
||||
}
|
||||
|
||||
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc)
|
||||
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc, void (*complete)(const char *, char ***, int *))
|
||||
{
|
||||
if(NULL == name || NULL == func || NULL == desc)
|
||||
{
|
||||
|
|
@ -34,6 +34,7 @@ void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv
|
|||
.name = name,
|
||||
.func = func,
|
||||
.desc = desc,
|
||||
.complete = complete,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +105,8 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
|
|||
int history_idx = linenoiseHistoryLen;
|
||||
|
||||
while (1) {
|
||||
if (read(STDIN_FILENO, &c, 1) == -1) return -1;
|
||||
ssize_t n = read(STDIN_FILENO, &c, 1);
|
||||
if (n <= 0) return -1;
|
||||
|
||||
if (c == '\n' || c == '\r') {
|
||||
buf[len] = 0;
|
||||
|
|
@ -164,7 +166,28 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
|
|||
if (completionCallback) {
|
||||
completionCallback(buf, &completions, &ncomp);
|
||||
if (ncomp > 0) {
|
||||
strncpy(buf, completions[0], bufsize - 1);
|
||||
/* 找到最后一个空格,只替换当前词,保留前缀 */
|
||||
char *last_space = NULL;
|
||||
for (int i = pos - 1; i >= 0; i--)
|
||||
{
|
||||
if (' ' == buf[i])
|
||||
{
|
||||
last_space = &buf[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != last_space)
|
||||
{
|
||||
int keep_len = last_space - buf + 1;
|
||||
strncpy(last_space + 1, completions[0], bufsize - keep_len - 1);
|
||||
buf[bufsize - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(buf, completions[0], bufsize - 1);
|
||||
}
|
||||
|
||||
len = pos = strlen(buf);
|
||||
SAFE_WRITE(STDOUT_FILENO, "\r\033[K", 4);
|
||||
SAFE_WRITE(STDOUT_FILENO, prompt, strlen(prompt));
|
||||
|
|
@ -189,7 +212,7 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
|
|||
|
||||
char *linenoise(const char *prompt) {
|
||||
char buf[1024];
|
||||
enableRawMode();
|
||||
if (enableRawMode() != 0) return NULL;
|
||||
int n = linenoiseEdit(buf, sizeof(buf), prompt);
|
||||
disableRawMode();
|
||||
if (n <= 0) return NULL;
|
||||
|
|
@ -236,9 +259,35 @@ stru_cmd *cmd_find(const char *name)
|
|||
|
||||
void cmd_complete(const char *buf, char ***completions, int *ncomp)
|
||||
{
|
||||
auto& s_cmd_list = get_cmd_list();
|
||||
|
||||
/* 判断是否有空格 —— 有空格则进入子命令补全 */
|
||||
const char *space = strchr(buf, ' ');
|
||||
if(NULL != space)
|
||||
{
|
||||
size_t cmd_len = space - buf;
|
||||
|
||||
for(auto &cmd : s_cmd_list)
|
||||
{
|
||||
if(0 == strncmp(cmd.name, buf, cmd_len) && '\0' == cmd.name[cmd_len])
|
||||
{
|
||||
if(NULL != cmd.complete)
|
||||
{
|
||||
cmd.complete(buf, completions, ncomp);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*ncomp = 0;
|
||||
*completions = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 无空格:命令名前缀匹配(原有逻辑) */
|
||||
int cnt = 0;
|
||||
char **c = NULL;
|
||||
auto& s_cmd_list = get_cmd_list();
|
||||
|
||||
for(auto &cmd : s_cmd_list)
|
||||
{
|
||||
|
|
@ -266,6 +315,38 @@ void cmd_complete(const char *buf, char ***completions, int *ncomp)
|
|||
}
|
||||
}
|
||||
|
||||
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp, const char **subs, int sub_count)
|
||||
{
|
||||
const char *prefix = strrchr(buf, ' ');
|
||||
if(NULL == prefix)
|
||||
{
|
||||
*ncomp = 0;
|
||||
*completions = NULL;
|
||||
return;
|
||||
}
|
||||
prefix++;
|
||||
|
||||
int cnt = 0;
|
||||
char **c = NULL;
|
||||
size_t prefix_len = strlen(prefix);
|
||||
|
||||
for(int i = 0; i < sub_count; i++)
|
||||
{
|
||||
if(0 == strncmp(subs[i], prefix, prefix_len))
|
||||
{
|
||||
if(NULL == c)
|
||||
{
|
||||
c = (char **)malloc(sizeof(char *) * (sub_count + 1));
|
||||
}
|
||||
c[cnt] = strdup(subs[i]);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
*completions = c;
|
||||
*ncomp = cnt;
|
||||
}
|
||||
|
||||
void cmd_help(int argc, char *argv[])
|
||||
{
|
||||
auto& s_cmd_list = get_cmd_list();
|
||||
|
|
|
|||
|
|
@ -12,13 +12,18 @@
|
|||
|
||||
LOCAL void cmd_recv()
|
||||
{
|
||||
char *line = linenoise("cmd > ");
|
||||
if(line == NULL)
|
||||
if(!isatty(STDIN_FILENO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(strlen(line) == 0)
|
||||
char *line = linenoise("cmd > ");
|
||||
if(NULL == line)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(0 == strlen(line))
|
||||
{
|
||||
free(line);
|
||||
return;
|
||||
|
|
@ -28,7 +33,7 @@ LOCAL void cmd_recv()
|
|||
|
||||
|
||||
char *orig_line = strdup(line);
|
||||
if(orig_line == NULL)
|
||||
if(NULL == orig_line)
|
||||
{
|
||||
free(line);
|
||||
return;
|
||||
|
|
@ -37,13 +42,13 @@ LOCAL void cmd_recv()
|
|||
char *argv[MAX_ARGC];
|
||||
int argc = 0;
|
||||
char *p = strtok(line, " \t");
|
||||
while(p != NULL && argc < MAX_ARGC)
|
||||
while(NULL != p && argc < MAX_ARGC)
|
||||
{
|
||||
argv[argc++] = p;
|
||||
p = strtok(NULL, " \t");
|
||||
}
|
||||
|
||||
if(argc == 0)
|
||||
if(0 == argc)
|
||||
{
|
||||
free(orig_line);
|
||||
free(line);
|
||||
|
|
@ -53,10 +58,10 @@ LOCAL void cmd_recv()
|
|||
stru_cmd *p_cmd = cmd_find(argv[0]);
|
||||
if(NULL == p_cmd)
|
||||
{
|
||||
if(strcmp(argv[0], "cd") == 0)
|
||||
if(0 == strcmp(argv[0], "cd"))
|
||||
{
|
||||
const char *path = (argc >= 2) ? argv[1] : getenv("HOME");
|
||||
if(path == NULL || chdir(path) != 0)
|
||||
if(NULL == path || 0 != chdir(path))
|
||||
{
|
||||
LOG_E("cd failed: %s", path ? path : "(null)");
|
||||
}
|
||||
|
|
@ -65,8 +70,7 @@ LOCAL void cmd_recv()
|
|||
return;
|
||||
}
|
||||
|
||||
// 如果不是内部命令,则尝试执行 Linux shell 命令
|
||||
if(system(orig_line) != 0)
|
||||
if(0 != system(orig_line))
|
||||
{
|
||||
LOG_E("shell command failed: %s", orig_line);
|
||||
}
|
||||
|
|
@ -82,7 +86,7 @@ LOCAL void cmd_recv()
|
|||
|
||||
int app_cmd_init1(void *arg)
|
||||
{
|
||||
// lineniseSetCompletionCallback(cmd_complete);
|
||||
lineniseSetCompletionCallback(cmd_complete);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -106,15 +110,15 @@ void *app_cmd(void *arg)
|
|||
|
||||
while(1)
|
||||
{
|
||||
task_event_recv(p_app->p_event,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER,
|
||||
task_event_recv(p_app->p_event,
|
||||
EV_TIMER1 | EV_TIMER2 | EV_TIMER3,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER,
|
||||
&event);
|
||||
|
||||
if(event & EV_TIMER1)
|
||||
{
|
||||
// cmd_recv();
|
||||
cmd_recv();
|
||||
}
|
||||
|
||||
if(event & EV_TIMER2)
|
||||
|
|
|
|||
|
|
@ -2432,6 +2432,12 @@ LOCAL void cmd_dc(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
CMD_REGISTER("datacenter", cmd_dc, "数据中心的控制命令");
|
||||
LOCAL void cmd_dc_complete(const char *buf, char ***completions, int *ncomp)
|
||||
{
|
||||
static const char *subs[] = {"out", "in", "yk", "ao", "param", "all"};
|
||||
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
|
||||
}
|
||||
|
||||
CMD_REGISTER("datacenter", cmd_dc, "数据中心的控制命令", cmd_dc_complete);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -514,4 +514,27 @@ LOCAL void cmd_iec(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
CMD_REGISTER("iec", cmd_iec, "iec线程的控制命令");
|
||||
LOCAL void cmd_iec_complete(const char *buf, char ***completions, int *ncomp)
|
||||
{
|
||||
int spaces = 0;
|
||||
for(const char *p = buf; *p; p++)
|
||||
{
|
||||
if(' ' == *p)
|
||||
{
|
||||
spaces++;
|
||||
}
|
||||
}
|
||||
|
||||
if(1 == spaces)
|
||||
{
|
||||
static const char *subs[] = {"run_cnt"};
|
||||
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
|
||||
}
|
||||
else if(2 == spaces)
|
||||
{
|
||||
static const char *subs[] = {"get", "reset"};
|
||||
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
CMD_REGISTER("iec", cmd_iec, "iec线程的控制命令", cmd_iec_complete);
|
||||
|
|
@ -875,4 +875,10 @@ LOCAL void cmd_iec61850m(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
CMD_REGISTER(MODULE_IEC61850M, cmd_iec61850m, "iec61850客户端线程的控制命令");
|
||||
LOCAL void cmd_iec61850m_complete(const char *buf, char ***completions, int *ncomp)
|
||||
{
|
||||
static const char *subs[] = {"info", "yk", "set"};
|
||||
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
|
||||
}
|
||||
|
||||
CMD_REGISTER(MODULE_IEC61850M, cmd_iec61850m, "iec61850客户端线程的控制命令", cmd_iec61850m_complete);
|
||||
|
|
@ -1207,8 +1207,13 @@ LOCAL void cmd_self_ptl(int argc, char *argv[])
|
|||
|
||||
}
|
||||
|
||||
LOCAL void cmd_self_ptl_complete(const char *buf, char ***completions, int *ncomp)
|
||||
{
|
||||
static const char *subs[] = {"1", "3", "5", "6", "9", "11"};
|
||||
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
|
||||
}
|
||||
|
||||
CMD_REGISTER("self_ptl", cmd_self_ptl, "私有规约的控制命令");
|
||||
CMD_REGISTER("self_ptl", cmd_self_ptl, "私有规约的控制命令", cmd_self_ptl_complete);
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue