boot中的命令行解析器

当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. 双引号中包含单引号:

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


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



 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值