基于MDK平台 cortex-M3 shell 的实现
2015-10-29 14:41
525 查看
每次写完代码最头疼的就是测试,大多数时间都得花在这里。要么用串口调试助手、要么用上位机。至于串口调度助手效率,大家都懂的。但又不想每次都写一个上位机、闲暇之余模仿u-boot和rtt-shell 写了一个shell,大多数代码都来自U-BOOT的、做了小小的阉割。
使用方法
/*在需要登记命令的文件内包含shell.h、console.h两个头文件 */
例:
REG_CMD --命令登记宏
(
printconf, --命令名
3, --命令的最大参数个数
do_printconf, --命令处理函数(函数的类型遵循 int (*cmd_callback)(struct cmd_tbl_t *, int argc, char **argv))
"显示系统配置", --简单的使用说明
"打印系统配置信息." --详细使用说明
);
另外由于所有的命令列表都编译到了cmdlist代码段,所以需要在编译器中设置防止cmdlist被优化。
暂时没心思写详细说明,直接给出代码。
代码主要由四个文件组成(Console.c、Console.h、shell.c、shell.h)
Console提供打印移植接口
/*console.h*/
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include "app_type.h"
void console_init(void);
void console_putc(const char c);
void console_puts(const char * s);
bool console_get(char *c);
char console_getc(void);
/*---对输入格式化字符串进行检测---*/
void console_printf (const char *fmt, ...) __attribute__((format(printf,1,2)));
#endif
/*console.c*/
#include "includes.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
/**==========================================================
*@brief 控制台初始化
*@param none
==========================================================*/
void console_init(void){}
/**==========================================================
*@brief 输出一个字符到串口控制台
*@param c
==========================================================*/
void console_putc(const char c){}
/**==========================================================
*@brief 输出一个字符串到串口控制台
*@param s
==========================================================*/
void console_puts(const char * s){}
/**==========================================================
*@brief 从串口控制台获取一个输入字符
*@retval true:成功获取
==========================================================*/
bool console_get(char *c){}
/**==========================================================
*@brief 从串口控制台获取一个输入字符
*@retval c
*@attetion 阻塞方式调用
==========================================================*/
char console_getc(void){}
static char printbuffer[128];
/**==========================================================
*@brief 打印一个格式化字符串到串口控制台
*@retval
==========================================================*/
void console_printf (const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vsprintf (printbuffer, fmt, args); //将输入参考格式化后放到缓冲区
va_end (args);
console_puts (printbuffer);
}
/*shell 提供命令处理*/
/*shell.h*/
/**********************************************************************
* @file shell.h
* @brief 命令行处理
*
* @version 1.0
* @date 2015-06-09
* @author roger
*
* Copyright(C) 2015
* All rights reserved.
* Copyright(C) 2015 QQ 932896234
* @reference u-boot
*
***********************************************************************/
#ifndef __SHELL_H_
#define __SHELL_H_
#ifndef NULL
#define NULL 0
#endif
#define CFG_MAXARGS 16 /*最大参数个数-----------------*/
#define CFG_MAXCMDS 30 /*最多允许定义的命令个数-------*/
/*----------------------------------------------------------------------------------------------------------
* Monitor Command Table
--------------------------------------------------------------------------------------------------------*/
typedef struct cmd_tbl_t
{
char *name;
/* 命令名 */
char maxargs;
/*最大参数个数 */
/*命令(处理)回调函数 */
int (*cmd_callback)(struct cmd_tbl_t *, int argc, char **argv);
char *usage;
/* 简单使用说明 */
char *help;
}cmd_tbl_t;
/*外部声明*/
int run_command(char *cmdline);
void run_shell(void);
char *readline (const char * prompt);
int parse_line(char *line, char *argv[]);
#define REG_CMD(name,maxargs,cmdProc,usage,help) \
const cmd_tbl_t __cmdline_##name \
__attribute__ ((unused,section ("cmdlist"))) \
= {#name, maxargs, cmdProc, usage,help}
#endif
/*shell.c*/
/**********************************************************************
* @file shell.c
* @brief 命令行处理程序
*
* @version 1.0
* @date 2015-06-09
* @author roger
*
* Copyright(C) 2015 QQ 932896234
* All rights reserved.
* reference u-boot
*
***********************************************************************/
#include "shell.h"
#include "console.h"
#include <string.h>
#define CFG_CBSIZE 64
static char console_buffer[CFG_CBSIZE]; /* */
#define erase_seq "\b \b" /* erase sequence */
static const char tab_seq[]=" "; /* used to expand TABs */
#define console_prompt "[Fire-fight]#"
#ifdef __CC_ARM /* ARM C Compiler */
extern const int cmdlist$$Base;
extern const int cmdlist$$Limit;
#define cmd_start cmdlist$$Base
#define cmd_end cmdlist$$Limit
#else
#error "The compiler does not support this shell."
#endif
/**====================================================================
* find command table entry for a command
* cmd_name :命令名
=======================================================================*/
cmd_tbl_t *find_cmd (const char *cmd_name)
{
cmd_tbl_t *cmdPtr;
const char *p;
int len;
/*==================================================================
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
-------------------------------------------------------------------*/
len = ((p = strchr(cmd_name, '.')) == NULL) ? strlen (cmd_name) : (p - cmd_name);
/*扫描所有命令========================================================*/
for ( cmdPtr = (cmd_tbl_t*)&cmd_start; cmdPtr < (cmd_tbl_t*)&cmd_end ; cmdPtr++)
{
if (strncmp (cmd_name, cmdPtr->name, len) == 0) /*匹配命令=======*/
{
if (len == strlen (cmdPtr->name))
return cmdPtr;
}
}
return NULL; /* not found or ambiguous command */
}
/***************************************************************************
*brief
*param
* buffer :字符缓冲区指针,
* p :指向当前字符的下一位置的指针
* colp :指向列计数
* np :指向已输出的字符数
* plen :提示符长度
*
***************************************************************************/
static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
{
char *s;
if (*np == 0)
{
return (p);
}
if (*(--p) == '\t') /* will retype the whole line */
{
while (*colp > plen)
{
console_puts (erase_seq);
(*colp)--;
}
for (s=buffer; s<p; ++s)
{
if (*s == '\t')
{
console_puts (tab_seq+((*colp) & 07));
*colp += 8 - ((*colp) & 07);
}
else
{
++(*colp);
console_putc (*s);
}
}
}
else
{
console_puts (erase_seq);
(*colp)--;
}
(*np)--;
return (p);
}
/***************************************************************************
* brief : 读一行
* param : prompt :命令行提示符
* Return: 输入的字符数
* -1 if break
* -2 if timed out
* 字符串将会放到console_buffer中
* attengion 调用该函数会阻塞当前进程运行
***************************************************************************/
char *readline (const char * prompt)
{
char *p = console_buffer;
int n = 0; /* buffer index */
int plen = 0; /* prompt length */
int col; /* output column cnt */
char c;
if (prompt) /*打印提示符 */
{
plen = strlen (prompt);
console_puts (prompt);
}
col = plen; /*光标位置 */
for (;;)
{
c = console_getc(); /*读取一个字符------------*/
/*
* Special character handling
*/
switch (c)
{
case '\r': /*回车键 */
case '\n':
*p = '\0'; /*加入结束符 */
console_puts ("\r\n");
return console_buffer; /*完成输入,返回输入字符个数*/
case '\0': /* nul */
continue;
case 0x03: /* ^C - break */
console_buffer[0] = '\0'; /* discard input */
return (NULL);
case 0x15: /* ^U - erase line */
while (col > plen) /*清空一行 */
{
console_puts (erase_seq); /*删除当前输入 */
--col;
}
p = console_buffer; /*重新指向缓冲区 */
n = 0;
continue;
case 0x17: /* ^W - erase word */
p=delete_char(console_buffer, p, &col, &n, plen);
while ((n > 0) && (*p != ' '))
{
p=delete_char(console_buffer, p, &col, &n, plen);
}
continue;
case 0x08: /* ^H - backspace */
case 0x7F: /* DEL - backspace */
p = delete_char(console_buffer, p, &col, &n, plen);
continue;
default:
/*
* 正常字符处理
*/
if (n < CFG_CBSIZE - 2)
{
if (c == '\t') { /* expand TABs */
console_puts (tab_seq+ (col&07));
col += 8 - (col&07);
}
else
{
++col; /*回显--------------*/
console_putc (c);
}
*p++ = c; /*将输入字符送到缓冲区*/
++n;
}
else
{ /*缓冲区满 */
console_putc ('\a');
}
}
}
}
/**************************************************************************
*brief 解析一行字符串
*param line
*output argv[] 参数列表
*return 参数个数
***************************************************************************/
int parse_line(char *line, char *argv[])
{
int nargs = 0; /*参数个数------------*/
#ifdef DEBUG_PARSER
console_printf ("parse_line: \"%s\"\n", line);
#endif
while (nargs < CFG_MAXARGS)
{
while ((*line == ' ') || (*line == '\t')) /*跳过空格及制表符-----*/
{
++line;
}
if (*line == '\0') /*判断是否到达字符串末尾*/
{
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
argv[nargs++] = line; /* begin of argument string*/
/* find end of string ------*/
while (*line && (*line != ' ') && (*line != '\t'))
{
++line;
}
if (*line == '\0') /*end of line, no more args*/
{
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
/*加入'\0'作为参数结尾标记 */
*line++ = '\0'; /* terminate current arg */
}
console_printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
static char *argv[CFG_MAXARGS + 1]; /*参数列表 */
/**===========================================================================
*@brief 运行一个命令
*@param cmdline 命令行
*@retval 0表示运行失败
============================================================================*/
int run_command(char *cmdline)
{
int argc; /*参数个数 */
cmd_tbl_t *cmdtp;
/* Extract arguments */
if ((argc = parse_line (cmdline, argv)) == 0)
{
return 0;
}
else if (strcmp(argv[0],"clear") == 0)
{
return 0;
}
/* 从命令表中查找一个命令-----------------------------------------------*/
if ((cmdtp = find_cmd(argv[0])) == NULL)
{
console_printf ("Unknown command '%s' - try 'help'\r\n", argv[0]);
return 0;
}
/* found - check max args */
if (argc > cmdtp->maxargs)
{
console_printf ("Usage:\n%s\n", cmdtp->usage);
console_printf ("argc=%d,maxargs=%d", argc , cmdtp->maxargs);
return 0;
}
if (cmdtp->cmdProc == NULL) /*判断处理函数是否存在*/
{
console_printf ("%s\r\n", cmdtp->usage);
}
/* OK - call function to run the command */
else
{
(cmdtp->cmdProc) (cmdtp, argc, argv);
}
return 1;
}
/*=============================================================
* for long help messages
=============================================================*/
int do_help (cmd_tbl_t * cmdtp, int argc, char *argv[])
{
int i;
int rcode = 0;
int j, swaps;
cmd_tbl_t *cmd_array[CFG_MAXCMDS];
/*计算出命令个数------------------------------------------*/
int cmd_items = (cmd_tbl_t*)&cmd_end - (cmd_tbl_t*)&cmd_start;
/*限制命令个数,避免缓冲区溢出-----------------------------*/
if (cmd_items > CFG_MAXCMDS)
{
cmd_items = CFG_MAXCMDS;
}
if (argc == 1)
{
cmdtp = (cmd_tbl_t *)&cmd_start;
for (i = 0; i < cmd_items; i++)
{
cmd_array[i] = cmdtp++;
}
/* 对命令列表进行排序---------------------------------*/
for (i = cmd_items - 1; i > 0; --i)
{
swaps = 0;
for (j = 0; j < i; ++j)
{
if (strcmp (cmd_array[j]->name,
cmd_array[j + 1]->name) > 0)
{
cmd_tbl_t *tmp;
tmp = cmd_array[j];
cmd_array[j] = cmd_array[j + 1];
cmd_array[j + 1] = tmp;
++swaps;
}
}
if (!swaps)
break;
}
console_puts("\r\n");
for (i = 0; i < cmd_items; i++)
{
console_puts(cmd_array[i]->name); /*打印命令名--------*/
/*对齐调整*/
j = strlen(cmd_array[i]->name);
if (j < 10)
{
j = 10 - j;
}
while (j--)console_putc(' ');
console_puts("- ");
console_puts(cmd_array[i]->usage); /*命令使用信息------*/
console_puts("\r\n");
}
return 0;
}
for (i = 1; i < argc; ++i) /*列出命令的详细信息*/
{
if ((cmdtp = find_cmd (argv[i])) != NULL)
{
console_puts (cmdtp->name);
console_puts (" :\r\n");
if (cmdtp->help)
{
console_puts (cmdtp->help);
}
else
{
console_puts ("- No help available.\n");
rcode = 1;
}
console_putc ('\n');
}
else
{
console_printf ("Unknown command '%s' - try 'help'"
" without arguments for list of all"
" known commands\n\n", argv[i]
);
rcode = 1;
}
}
return rcode;
}
/**==========================================================================
登记帮助命令
============================================================================*/
REG_CMD
(
help, CFG_MAXARGS, do_help,
"print online help",
""
);
const cmd_tbl_t __cmdline_help_ __attribute__ ((unused,section ("cmdlist"))) =
{
"?", CFG_MAXARGS,do_help,
"alias for 'help'",
""
};
/**===========================================================================
*@brief 运行命令行系统
============================================================================*/
void run_shell(void)
{
char *cmdline;
cmdline = readline(console_prompt); /*读一行 */
if (cmdline == NULL)return;
if (strlen(cmdline) >= CFG_CBSIZE)
{
console_puts ("## Command too long!\n");
return;
}
run_command(cmdline);
}
使用方法
/*在需要登记命令的文件内包含shell.h、console.h两个头文件 */
例:
REG_CMD --命令登记宏
(
printconf, --命令名
3, --命令的最大参数个数
do_printconf, --命令处理函数(函数的类型遵循 int (*cmd_callback)(struct cmd_tbl_t *, int argc, char **argv))
"显示系统配置", --简单的使用说明
"打印系统配置信息." --详细使用说明
);
另外由于所有的命令列表都编译到了cmdlist代码段,所以需要在编译器中设置防止cmdlist被优化。
暂时没心思写详细说明,直接给出代码。
代码主要由四个文件组成(Console.c、Console.h、shell.c、shell.h)
Console提供打印移植接口
/*console.h*/
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
#include "app_type.h"
void console_init(void);
void console_putc(const char c);
void console_puts(const char * s);
bool console_get(char *c);
char console_getc(void);
/*---对输入格式化字符串进行检测---*/
void console_printf (const char *fmt, ...) __attribute__((format(printf,1,2)));
#endif
/*console.c*/
#include "includes.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
/**==========================================================
*@brief 控制台初始化
*@param none
==========================================================*/
void console_init(void){}
/**==========================================================
*@brief 输出一个字符到串口控制台
*@param c
==========================================================*/
void console_putc(const char c){}
/**==========================================================
*@brief 输出一个字符串到串口控制台
*@param s
==========================================================*/
void console_puts(const char * s){}
/**==========================================================
*@brief 从串口控制台获取一个输入字符
*@retval true:成功获取
==========================================================*/
bool console_get(char *c){}
/**==========================================================
*@brief 从串口控制台获取一个输入字符
*@retval c
*@attetion 阻塞方式调用
==========================================================*/
char console_getc(void){}
static char printbuffer[128];
/**==========================================================
*@brief 打印一个格式化字符串到串口控制台
*@retval
==========================================================*/
void console_printf (const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vsprintf (printbuffer, fmt, args); //将输入参考格式化后放到缓冲区
va_end (args);
console_puts (printbuffer);
}
/*shell 提供命令处理*/
/*shell.h*/
/**********************************************************************
* @file shell.h
* @brief 命令行处理
*
* @version 1.0
* @date 2015-06-09
* @author roger
*
* Copyright(C) 2015
* All rights reserved.
* Copyright(C) 2015 QQ 932896234
* @reference u-boot
*
***********************************************************************/
#ifndef __SHELL_H_
#define __SHELL_H_
#ifndef NULL
#define NULL 0
#endif
#define CFG_MAXARGS 16 /*最大参数个数-----------------*/
#define CFG_MAXCMDS 30 /*最多允许定义的命令个数-------*/
/*----------------------------------------------------------------------------------------------------------
* Monitor Command Table
--------------------------------------------------------------------------------------------------------*/
typedef struct cmd_tbl_t
{
char *name;
/* 命令名 */
char maxargs;
/*最大参数个数 */
/*命令(处理)回调函数 */
int (*cmd_callback)(struct cmd_tbl_t *, int argc, char **argv);
char *usage;
/* 简单使用说明 */
char *help;
}cmd_tbl_t;
/*外部声明*/
int run_command(char *cmdline);
void run_shell(void);
char *readline (const char * prompt);
int parse_line(char *line, char *argv[]);
#define REG_CMD(name,maxargs,cmdProc,usage,help) \
const cmd_tbl_t __cmdline_##name \
__attribute__ ((unused,section ("cmdlist"))) \
= {#name, maxargs, cmdProc, usage,help}
#endif
/*shell.c*/
/**********************************************************************
* @file shell.c
* @brief 命令行处理程序
*
* @version 1.0
* @date 2015-06-09
* @author roger
*
* Copyright(C) 2015 QQ 932896234
* All rights reserved.
* reference u-boot
*
***********************************************************************/
#include "shell.h"
#include "console.h"
#include <string.h>
#define CFG_CBSIZE 64
static char console_buffer[CFG_CBSIZE]; /* */
#define erase_seq "\b \b" /* erase sequence */
static const char tab_seq[]=" "; /* used to expand TABs */
#define console_prompt "[Fire-fight]#"
#ifdef __CC_ARM /* ARM C Compiler */
extern const int cmdlist$$Base;
extern const int cmdlist$$Limit;
#define cmd_start cmdlist$$Base
#define cmd_end cmdlist$$Limit
#else
#error "The compiler does not support this shell."
#endif
/**====================================================================
* find command table entry for a command
* cmd_name :命令名
=======================================================================*/
cmd_tbl_t *find_cmd (const char *cmd_name)
{
cmd_tbl_t *cmdPtr;
const char *p;
int len;
/*==================================================================
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
-------------------------------------------------------------------*/
len = ((p = strchr(cmd_name, '.')) == NULL) ? strlen (cmd_name) : (p - cmd_name);
/*扫描所有命令========================================================*/
for ( cmdPtr = (cmd_tbl_t*)&cmd_start; cmdPtr < (cmd_tbl_t*)&cmd_end ; cmdPtr++)
{
if (strncmp (cmd_name, cmdPtr->name, len) == 0) /*匹配命令=======*/
{
if (len == strlen (cmdPtr->name))
return cmdPtr;
}
}
return NULL; /* not found or ambiguous command */
}
/***************************************************************************
*brief
*param
* buffer :字符缓冲区指针,
* p :指向当前字符的下一位置的指针
* colp :指向列计数
* np :指向已输出的字符数
* plen :提示符长度
*
***************************************************************************/
static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
{
char *s;
if (*np == 0)
{
return (p);
}
if (*(--p) == '\t') /* will retype the whole line */
{
while (*colp > plen)
{
console_puts (erase_seq);
(*colp)--;
}
for (s=buffer; s<p; ++s)
{
if (*s == '\t')
{
console_puts (tab_seq+((*colp) & 07));
*colp += 8 - ((*colp) & 07);
}
else
{
++(*colp);
console_putc (*s);
}
}
}
else
{
console_puts (erase_seq);
(*colp)--;
}
(*np)--;
return (p);
}
/***************************************************************************
* brief : 读一行
* param : prompt :命令行提示符
* Return: 输入的字符数
* -1 if break
* -2 if timed out
* 字符串将会放到console_buffer中
* attengion 调用该函数会阻塞当前进程运行
***************************************************************************/
char *readline (const char * prompt)
{
char *p = console_buffer;
int n = 0; /* buffer index */
int plen = 0; /* prompt length */
int col; /* output column cnt */
char c;
if (prompt) /*打印提示符 */
{
plen = strlen (prompt);
console_puts (prompt);
}
col = plen; /*光标位置 */
for (;;)
{
c = console_getc(); /*读取一个字符------------*/
/*
* Special character handling
*/
switch (c)
{
case '\r': /*回车键 */
case '\n':
*p = '\0'; /*加入结束符 */
console_puts ("\r\n");
return console_buffer; /*完成输入,返回输入字符个数*/
case '\0': /* nul */
continue;
case 0x03: /* ^C - break */
console_buffer[0] = '\0'; /* discard input */
return (NULL);
case 0x15: /* ^U - erase line */
while (col > plen) /*清空一行 */
{
console_puts (erase_seq); /*删除当前输入 */
--col;
}
p = console_buffer; /*重新指向缓冲区 */
n = 0;
continue;
case 0x17: /* ^W - erase word */
p=delete_char(console_buffer, p, &col, &n, plen);
while ((n > 0) && (*p != ' '))
{
p=delete_char(console_buffer, p, &col, &n, plen);
}
continue;
case 0x08: /* ^H - backspace */
case 0x7F: /* DEL - backspace */
p = delete_char(console_buffer, p, &col, &n, plen);
continue;
default:
/*
* 正常字符处理
*/
if (n < CFG_CBSIZE - 2)
{
if (c == '\t') { /* expand TABs */
console_puts (tab_seq+ (col&07));
col += 8 - (col&07);
}
else
{
++col; /*回显--------------*/
console_putc (c);
}
*p++ = c; /*将输入字符送到缓冲区*/
++n;
}
else
{ /*缓冲区满 */
console_putc ('\a');
}
}
}
}
/**************************************************************************
*brief 解析一行字符串
*param line
*output argv[] 参数列表
*return 参数个数
***************************************************************************/
int parse_line(char *line, char *argv[])
{
int nargs = 0; /*参数个数------------*/
#ifdef DEBUG_PARSER
console_printf ("parse_line: \"%s\"\n", line);
#endif
while (nargs < CFG_MAXARGS)
{
while ((*line == ' ') || (*line == '\t')) /*跳过空格及制表符-----*/
{
++line;
}
if (*line == '\0') /*判断是否到达字符串末尾*/
{
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
argv[nargs++] = line; /* begin of argument string*/
/* find end of string ------*/
while (*line && (*line != ' ') && (*line != '\t'))
{
++line;
}
if (*line == '\0') /*end of line, no more args*/
{
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
/*加入'\0'作为参数结尾标记 */
*line++ = '\0'; /* terminate current arg */
}
console_printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);
#ifdef DEBUG_PARSER
console_printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}
static char *argv[CFG_MAXARGS + 1]; /*参数列表 */
/**===========================================================================
*@brief 运行一个命令
*@param cmdline 命令行
*@retval 0表示运行失败
============================================================================*/
int run_command(char *cmdline)
{
int argc; /*参数个数 */
cmd_tbl_t *cmdtp;
/* Extract arguments */
if ((argc = parse_line (cmdline, argv)) == 0)
{
return 0;
}
else if (strcmp(argv[0],"clear") == 0)
{
return 0;
}
/* 从命令表中查找一个命令-----------------------------------------------*/
if ((cmdtp = find_cmd(argv[0])) == NULL)
{
console_printf ("Unknown command '%s' - try 'help'\r\n", argv[0]);
return 0;
}
/* found - check max args */
if (argc > cmdtp->maxargs)
{
console_printf ("Usage:\n%s\n", cmdtp->usage);
console_printf ("argc=%d,maxargs=%d", argc , cmdtp->maxargs);
return 0;
}
if (cmdtp->cmdProc == NULL) /*判断处理函数是否存在*/
{
console_printf ("%s\r\n", cmdtp->usage);
}
/* OK - call function to run the command */
else
{
(cmdtp->cmdProc) (cmdtp, argc, argv);
}
return 1;
}
/*=============================================================
* for long help messages
=============================================================*/
int do_help (cmd_tbl_t * cmdtp, int argc, char *argv[])
{
int i;
int rcode = 0;
int j, swaps;
cmd_tbl_t *cmd_array[CFG_MAXCMDS];
/*计算出命令个数------------------------------------------*/
int cmd_items = (cmd_tbl_t*)&cmd_end - (cmd_tbl_t*)&cmd_start;
/*限制命令个数,避免缓冲区溢出-----------------------------*/
if (cmd_items > CFG_MAXCMDS)
{
cmd_items = CFG_MAXCMDS;
}
if (argc == 1)
{
cmdtp = (cmd_tbl_t *)&cmd_start;
for (i = 0; i < cmd_items; i++)
{
cmd_array[i] = cmdtp++;
}
/* 对命令列表进行排序---------------------------------*/
for (i = cmd_items - 1; i > 0; --i)
{
swaps = 0;
for (j = 0; j < i; ++j)
{
if (strcmp (cmd_array[j]->name,
cmd_array[j + 1]->name) > 0)
{
cmd_tbl_t *tmp;
tmp = cmd_array[j];
cmd_array[j] = cmd_array[j + 1];
cmd_array[j + 1] = tmp;
++swaps;
}
}
if (!swaps)
break;
}
console_puts("\r\n");
for (i = 0; i < cmd_items; i++)
{
console_puts(cmd_array[i]->name); /*打印命令名--------*/
/*对齐调整*/
j = strlen(cmd_array[i]->name);
if (j < 10)
{
j = 10 - j;
}
while (j--)console_putc(' ');
console_puts("- ");
console_puts(cmd_array[i]->usage); /*命令使用信息------*/
console_puts("\r\n");
}
return 0;
}
for (i = 1; i < argc; ++i) /*列出命令的详细信息*/
{
if ((cmdtp = find_cmd (argv[i])) != NULL)
{
console_puts (cmdtp->name);
console_puts (" :\r\n");
if (cmdtp->help)
{
console_puts (cmdtp->help);
}
else
{
console_puts ("- No help available.\n");
rcode = 1;
}
console_putc ('\n');
}
else
{
console_printf ("Unknown command '%s' - try 'help'"
" without arguments for list of all"
" known commands\n\n", argv[i]
);
rcode = 1;
}
}
return rcode;
}
/**==========================================================================
登记帮助命令
============================================================================*/
REG_CMD
(
help, CFG_MAXARGS, do_help,
"print online help",
""
);
const cmd_tbl_t __cmdline_help_ __attribute__ ((unused,section ("cmdlist"))) =
{
"?", CFG_MAXARGS,do_help,
"alias for 'help'",
""
};
/**===========================================================================
*@brief 运行命令行系统
============================================================================*/
void run_shell(void)
{
char *cmdline;
cmdline = readline(console_prompt); /*读一行 */
if (cmdline == NULL)return;
if (strlen(cmdline) >= CFG_CBSIZE)
{
console_puts ("## Command too long!\n");
return;
}
run_command(cmdline);
}
相关文章推荐
- bash 快捷键
- Shell编程
- LinuxShell算术运算
- linux shell中28个特殊字符的作用
- Shell统计访问ip UV、PV
- linux bash shell 流程控制(if/else )
- shell中条件测试与整数运算以及脚本选项
- Shell中uniq与sort -u两种去重的对比
- xshell 账号密码文件位置
- bash: ./t.sh:/bin/bash^M:损坏的解释器: 没有那个文件或目录
- Shell 同时读取多个文件
- Shell统计
- Bash 及其特性
- shell批量增删改查百库百表(mysql)
- Shell中read的选项及用法
- linux shell 编程3 判断当前的是不是目录、 传递参数的个数
- 退出Python的shell
- shell脚本 小试一下
- mysqlcheck命令时提示: bash: mysqlcheck: command not found
- shell脚本学习之旅