在语法或code中的错误? [英] Is the bug in the grammar or in the code?
问题描述
我不知道这是语法的shell命令语言,还应该能够执行单引号和双引号是正确的。如此看来,非普通的命令,例如工作 LS -al |排序|厕所-l
,但简单的不使用单引号工作:回声'富巴
不起作用。
I'm not sure if this grammar is correct for a shell command language that should also be able to execute single-quotes and double-quotes. It seems that non-trivial commands work e.g. ls -al | sort | wc -l
but the simple one does not work with single-quotes: echo 'foo bar'
does not work.
%{
#include "shellparser.h"
%}
%option reentrant
%option noyywrap
%x SINGLE_QUOTED
%x DOUBLE_QUOTED
%%
"|" { return PIPE; }
[ \t\r] { }
[\n] { return EOL; }
[a-zA-Z0-9_\.\-]+ { return FILENAME; }
['] { BEGIN(SINGLE_QUOTED); }
<SINGLE_QUOTED>[^']+ { }
<SINGLE_QUOTED>['] { BEGIN(INITIAL); return ARGUMENT; }
<SINGLE_QUOTED><<EOF>> { return -1; }
["] { BEGIN(DOUBLE_QUOTED); }
<DOUBLE_QUOTED>[^"]+ { }
<DOUBLE_QUOTED>["] { BEGIN(INITIAL); return ARGUMENT; }
<DOUBLE_QUOTED><<EOF>> { return -1; }
[^ \t\r\n|'"]+ { return ARGUMENT; }
%%
我的code,扫描和解析壳
My code that scans and parses the shell is
params[0] = NULL;
printf("> ");
i=1;
do {
lexCode = yylex(scanner);
text = strdup(yyget_text(scanner));//yyget_text(scanner);
/*printf("lexCode %d command %s inc:%d", lexCode, text, i);*/
ca = text;
if (lexCode != EOL) {
params[i++] = text;
}
Parse(shellParser, lexCode, text);
if (lexCode == EOL) {
dump_argv("Before exec_arguments", i, params);
exec_arguments(i, params);
corpse_collector();
Parse(shellParser, 0, NULL);
i=1;
}
} while (lexCode > 0);
if (-1 == lexCode) {
fprintf(stderr, "The scanner encountered an error.\n");
}
CMake的构建文件
The CMake build file is
cmake_minimum_required(VERSION 3.0)
project(openshell)
find_package(FLEX)
FLEX_TARGET(ShellScanner shellscanner.l shellscanner.c)
set(CMAKE_VERBOSE_MAKEFILE on)
include_directories(/usr/include/readline)
ADD_EXECUTABLE(lemon lemon.c)
add_custom_command(OUTPUT shellparser.c COMMAND lemon -s shellparser.y DEPENDS shellparser.y)
add_executable(openshell shellparser.c ${FLEX_ShellScanner_OUTPUTS} main.c openshell.h errors.c errors.h util.c util.h stack.c stack.h shellscanner.l shellscanner.h)
file(GLOB SOURCES "./*.c")
target_link_libraries(openshell ${READLINE_LIBRARY} ${FLEX_LIBRARIES})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -std=c99")
我的项目可在我github上。一个典型的shell会话,其中只有一些命令来一些bug因工作,如下。
My project is available on my github. A typical shell session, where only some commands work due to some bug, is as follows.
> ls -al | sort | wc
argument ::= FILENAME .
argumentList ::= argument .
command ::= FILENAME argumentList .
command ::= FILENAME .
command ::= FILENAME .
commandList ::= command .
commandList ::= command PIPE commandList .
commandList ::= command PIPE commandList .
{(null)} {ls} {-al} {|} {sort} {|} {wc}
45 398 2270
3874: child 3881 status 0x0000
in ::= in commandList EOL .
> who
command ::= FILENAME .
commandList ::= command .
{(null)} {who}
dac :0 2016-04-18 05:17 (:0)
dac pts/2 2016-04-18 05:20 (:0)
3874: child 3887 status 0x0000
in ::= in commandList EOL .
> ls -al | awk '{print $1}'
argument ::= FILENAME .
argumentList ::= argument .
command ::= FILENAME argumentList .
argument ::= ARGUMENT .
argumentList ::= argument .
command ::= FILENAME argumentList .
commandList ::= command .
commandList ::= command PIPE commandList .
{(null)} {ls} {-al} {|} {awk} {'}
awk: cmd. line:1: '
awk: cmd. line:1: ^ invalid char ''' in expression
3874: child 3896 status 0x0100
in ::= in commandList EOL .
>
我可以观察到两个命令得到同样的错误:回声'富巴
被乱码到 {回声} {'}
的时候,我们希望它导致 {回声} {foo的酒吧}
,使壳去掉引号像这样执行命令
I can observe that both commands get the same bug: echo 'foo bar'
gets garbled to {echo} {'}
when we want it to result in {echo} {foo bar}
so that the shell strips the quotes and executes the command like this
的char * CMD [] = {在/ usr /斌/回声,富巴,0};
推荐答案
这个问题在规则
&LT; SINGLE_QUOTED&GT; [^'] + {}
,因为它消除了引号内的所有字符。你得到的是yytext中为收盘报价(由于规则&LT; SINGLE_QUOTED&GT;'] ...
)。你必须从某个地方存储文本,并在检测结束引号时使用它。例如。 (非常差的编码风格,错误检查等省略了,不好意思)
since it removes all characters inside quotes. All you get as "yytext" is the closing quote (due to rule <SINGLE_QUOTED>['] ...
). You have to store somewhere the text and use it when the closing quote is detected. E.g. (very poor coding style, error checking etc. omitted, sorry)
<SINGLE_QUOTED>[^']+ { mystring = strdup(yytext); }
<SINGLE_QUOTED>['] { BEGIN(INITIAL);
/* mystring contains the whole string now,
yytext contains only "'" */
return ARGUMENT; }
这篇关于在语法或code中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!