boot中的命令行解析器

来源:互联网 发布:素颜美女知乎 编辑:程序博客网 时间:2024/06/13 23:22

当boot从终端读取一行输入后,该怎么解释执行呢,怎么判断一条命令什么时候结束,用户输入的是一条命令还是多条命令?

下面是boot中的部分重要代码片段:

int boot_docommands(char *buf){    queue_t cmdqueue;    ui_command_t *cmd;    int status = CMD_ERR_BLANK;    int term;    q_init(&cmdqueue);    while ((cmd = cmd_readcommand(&buf))) {q_enqueue(&cmdqueue,(queue_t *) cmd);}    while ((cmd = (ui_command_t *) q_deqnext(&(cmdqueue)))) {    if (env_getenv("CMD_ECHO"))printf("{CMD} <%s>\n", cmd->ptr);status = ui_docommand(cmd->ptr);term = cmd->term;KFREE(cmd);if (status == CMD_ERR_BLANK) continue;/* * And causes us to stop at the first failure. */if ((term == CMD_TERM_AND) && (status != 0)) break;/* * OR causes us to stop at the first success. */if ((term == CMD_TERM_OR) && (status == 0)) break;/* * Neither AND nor OR causes us to keep chugging away. */}    return status;}ui_command_t *cmd_readcommand(char **pptr){    char *ptr = *pptr;    int insquote = FALSE;    int indquote = FALSE;    ui_command_t *cmd;    int term = CMD_TERM_EOL;    int termlen = 0;    while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) ptr++;    *pptr = ptr;    if (!*ptr) return NULL;    while (*ptr) {if (!insquote && !indquote) {    if ((*ptr == ';') || (*ptr == '\n')) {term = CMD_TERM_SEMI;termlen = 1;break;}    if ((*ptr == '&') && (*(ptr+1) == '&')) {term = CMD_TERM_AND;termlen = 2;break;}    if ((*ptr == '|') && (*(ptr+1) == '|')) {term = CMD_TERM_OR;termlen = 2;break;}    }if (*ptr == '\'') {    insquote = !insquote;    ptr++;    continue;    }if (!insquote) {    if (*ptr == '"') {indquote = !indquote;ptr++;continue;}    }if (!insquote && (*ptr == '\\')) {    ptr++;/* skip the backslash */    if (*ptr) ptr++;/* skip escaped char */    continue;    }ptr++;}    ptr += termlen;    cmd = (ui_command_t *) KMALLOC((sizeof(ui_cmdline_t) + (ptr-*pptr) - termlen + 1),0);    memcpy((char *)(cmd+1),*pptr,ptr-*pptr-termlen);    cmd->ptr= (char *) (cmd+1);    cmd->term = term;    cmd->ptr[ptr-*pptr-termlen] = 0;    *pptr = ptr;    return cmd;}

insquote表示处在单引号中,indquote表示处在双引号中

1. 首先考虑没有单引号和双引号的情况:

碰到下列字符表示一条命令的结束:

  • 碰到';'或'\n'字符
  • 碰到两个&&
  • 碰到两个||
碰到转义字符'\',则直接跳过转义符后面的字符。

2. 只有单引号的情况:

单引号不能嵌套,因为单引号左边跟右边是同一个字符,因此嵌套深度不知道是该加一还是减一。单引号中可以包含任何字符,包括双引号,反斜杠\,但任何字符都看做普通字符,直到碰到下一个单引号(跟在转义字符之后的单引号也算),单引号才算结束。


3. 只有双引号的情况:

双引号也不能嵌套,原因跟单引号一样,左右部分相同。双引号中支持转义字符,因此碰到\" 双引号不算结束。


4. 单引号中包含双引号:

这种情况较简单,因为单引号中的都看做普通字符


5. 双引号中包含单引号:

双引号中可以包含单引号,碰到单引号后当做特殊字符来处理,直到碰到下一个单引号结束,其他情况跟只有双引号一样。


另外注意组合命令的处理,&& 只有当前面一条命令执行成功才执行后面的命令, ||表示前面的命令执行失败了才执行后面的命令。



 


原创粉丝点击