基本思路
- 读取命令我采取的读取整个字符串后再进行分段和分析:
- 首先是parse_token将字符串通过分号为分隔,得到每组命令,每组命令当中只包含管道,输入输出重定向和单条命令及其参数。
- 然后是parse_group将每段得到的字符串通过管道为分隔,得到只包含参数,输入输出重定向和单条命令的更加简单的命令串
- 最后是parse_command分析单条指令,得到输入输出重定向的文件流和命令的属性还有命令的参数。
- 从内存中取出占位放入命令,然后将命令分组(组内连续)
具体实现:
void parse_token ( char* buf )
{
int n = strlen ( buf ),i,j=0;
n--;
buf[n] = 0;
for ( i = 0 ; i < n ; i++ )
if ( buf[i] == ';'|| i == n-1 )
{
if ( buf[i] == ';' )
buf[i] = 0;
parse_group ( buf+j );
j = i+1;
}
}
- 然后是parse_group,与parse_token思路相似
void parse_group ( char* buf )
{
int n = strlen ( buf ),i,j=0;
int x = cnt_cmd;
for ( i = 0 ; i < n ; i++ )
if ( buf[i] == '|' || i == n-1 )
{
int mode = 0;
if ( buf[i] == '|' )
{
buf[i] = 0;
mode = 1;
}
parse_command ( buf+j , mode );
j = i+1;
}
group[cnt_group].first = x;
group[cnt_group].last = cnt_cmd;
cnt_group++;
}
void parse_command ( char* buf , int mode )
{
int n = strlen ( buf ),i=0,j=0;
while ( buf[i] ==' '|| buf[i] == '\t' ) i++,j++;
int id = init_cmd ();
if ( mode == 1 ) cmd[id].type |= PIPE;
char* segment[MAX_ARGS];
int x=0;
for ( ; i < n ; i++ )
if ( buf[i] == ' ' || i == n-1 )
{
if ( buf[i] == ' ' ) buf[i] = 0;
segment[x++] = buf+j;
j = i+1;
while ( buf[j] == ' ' || buf[j] == '\t' )
j++,i++;
}
int temp = 0;
cmd[id].cmd = segment[0];
cmd[id].param = malloc(sizeof (char*)*(MAX_ARGS+2) );
if ( x > 0 )
cmd[id].param[temp++] = segment[0];
for ( i = 1; i < x ; i++ )
{
int flag = 1;
if ( strlen(segment[i]) == 1 )
{
if ( segment[i][0] == '<' )
{
flag = 0;
cmd[id].input = segment[i+1];
i++;
}
else if ( segment[i][0] == '>' )
{
flag = 0;
cmd[id].output = segment[i+1];
i++;
}
}
if ( strlen ( segment[i] ) == 2 )
{
if ( strcmp ( segment[i] , "<<" ) == 0 )
{
flag = 0;
cmd[id].input = segment[i+1];
i++;
}
else if ( strcmp ( segment[i] , ">>" ) == 0 )
{
flag = 0;
cmd[id].output = segment[i+1];
i++;
}
}
if ( flag )
{
cmd[id].param[temp++] = segment[i];
}
}
}
需要用到的函数库中的函数
- string.h里的一些简单的字符串操作函数
- char* flag = fgets ( buf , BUFSIZE , stdin);用于读取一行数据的函数,第一个是缓存区间的首地址,第二个为缓存区间的规模,第三个为输入流
- malloc向堆申请内存