解析器(parsing.c):
#include "main.h"
#ifdef DEBUG_PRINT
void printAST(cmd_p root, int tab) {
if (root == NULL) return;
list_cmd *lcmd;
exec_cmd *ecmd;
pipe_cmd *pcmd;
back_cmd *bcmd;
redir_cmd *rcmd;
int cur_arg = 0;
for (int i = 0; i < tab; ++i)
fprintf(stderr, " ");
switch (root->type) {
case BLOCK:
fprintf(stderr, "BLOCK\n");
printAST(((block_cmd *)root)->subcmd, tab + 1);
break;
case LIST:
fprintf(stderr, "LIST\n");
lcmd = (list_cmd *)root;
printAST(lcmd->left, tab + 1);
printAST(lcmd->right, tab + 1);
break;
case PIPE:
fprintf(stderr, "PIPE\n");
pcmd = (pipe_cmd *)root;
printAST(pcmd->left, tab + 1);
printAST(pcmd->right, tab + 1);
break;
case REDIR:
fprintf(stderr, "REDIR\n");
rcmd = (redir_cmd *)root;
printAST(rcmd->cmd, tab + 1);
for (int i = 0; i < tab; ++i) fprintf(stderr, " ");
// switch(rcmd->mode) {
// case O_WRONLY | O_APPEND | O_CREAT:
// printf("APPEND TO:");
// break;
// case O_RDONLY:
// printf("READ FROM:");
// break;
// default:
// printf("REWRITE TO:");
// break;
// }
fprintf(stderr, "%s\n", rcmd->fileb);
break;
case BACK:
fprintf(stderr, "BACK\n");
bcmd = (back_cmd *)root;
printAST(bcmd->back, tab + 1);
break;
case EXEC:
fprintf(stderr, "EXEC\n");
ecmd = (exec_cmd *)root;
// for (int i = 0; i < tab; ++i)
// fprintf(stderr, " ");
// printf(" ARGS:\n");
// while (ecmd->largs[cur_arg] != NULL) {
// for (int i = 0; i < tab; ++i)
// printf(" ");
// printf(" ");
// printf("%s\n", ecmd->largs[cur_arg]);
// //*(ecmd->rargs[cur_arg]) = 0;
// ++cur_arg;
// }
break;
}
}
#endif
static int checkChar(char* *beg, char* end, char c) {
char* cur = *beg;
while (cur < end && strchr(whiteChars, *cur) != NULL)
++cur;
*beg = cur;
return (c == *cur);
}
static int getToken(char* *beg, char* end, char* *needle_beg, char* *needle_end) {
char* cur = *beg;
int ret;
while (cur < end && strchr(whiteChars, *cur)) ++cur;
if (needle_beg != NULL) *needle_beg = cur;
switch (*cur) {
case 0:
ret = END;
break;
case '|': case '(': case ')': case '&': case ';':
++cur;
ret = SPECIAL;
break;
case '<':
++cur;
ret = READ;
break;
case '>':
++cur;
ret = ((*cur) == '>') ? APPEND : REWRITE;
if (ret == APPEND) ++cur;
break;
default:
ret = BASIC;
while (cur < end && !strchr(whiteChars, *cur) && !strchr("|()&<>;", *cur))
++cur;
if (needle_end != NULL) *needle_end = cur;
break;
}
*beg = cur;
return ret;
}
static cmd_p parseline(char* *beg, char* end);
static cmd_p parseRedir(cmd_p ret, char* *beg, char* end);
static cmd_p parseblock(char* *beg, char* end) {
cmd_p ret;
if (checkChar(beg, end, '(') == 0) parse_errcode++;
getToken(beg, end, NULL, NULL);
ret = parseline(beg, end);
ret = new_Block_cmd(ret);
if (checkChar(beg, end, ')') == 0) parse_errcode++;
getToken(beg, end, NULL, NULL);
ret = parseRedir(ret, beg, end);
return ret;
}
static cmd_p parseRedir(cmd_p ret, char* *beg, char* end) {
char* needle_beg, *needle_end;
while (checkChar(beg, end, '<') || checkChar(beg, end, '>')) {
int tok = getToken(beg, end, NULL, NULL);
if (BASIC != getToken(beg, end, &needle_beg, &needle_end))
parse_errcode++;
switch (tok) {
case APPEND:
ret = new_Redir_cmd(ret, needle_beg, needle_end,
O_WRONLY | O_APPEND | O_CREAT, 1);
break;
case REWRITE:
ret = new_Redir_cmd(ret, needle_beg, needle_end,
O_WRONLY | O_TRUNC | O_CREAT, 1);
break;
case READ:
ret = new_Redir_cmd(ret, needle_beg, needle_end, O_RDONLY, 0);
break;
}
}
return ret;
}
static cmd_p parseexec(char* *beg, char* end) {
char* needle_beg, *needle_end;
cmd_p ret;
if (checkChar(beg, end, '(')) return ret = parseblock(beg, end);
ret = new_Exec_cmd();
exec_cmd *cmd = (exec_cmd *)ret;
ret = parseRedir(ret, beg, end);
int argc = 0;
while (!checkChar(beg, end, '|') && !checkChar(beg, end, '&') &&
!checkChar(beg, end, ')') && !checkChar(beg, end, ';') &&
!checkChar(beg, end, '<') && !checkChar(beg, end, '>')) {
int result = getToken(beg, end, &needle_beg, &needle_end);
if (result == END) break;
if (result != BASIC) parse_errcode++;
cmd->largs[argc] = needle_beg, cmd->rargs[argc] = needle_end;
if ((++argc) > 256) {parse_errcode++; break;}
}
ret = parseRedir(ret, beg, end);
if (argc == 0) parse_errcode++;
cmd->largs[argc] = cmd->rargs[argc] = NULL;
return ret;
}
static cmd_p parsepipe(char* *beg, char* end) {
cmd_p left = parseexec(beg, end);
cmd_p ret = left;
if (checkChar(beg, end, '|')) {
getToken(beg, end, NULL, NULL);
cmd_p right = parsepipe(beg, end);
if (left == NULL || right == NULL) parse_errcode++;
ret = new_Pipe_cmd(ret, right);
}
return ret;
}
static cmd_p parseline(char* *beg, char* end) {
cmd_p ret = parsepipe(beg, end);
if (checkChar(beg, end, '&')) {
getToken(beg, end, NULL, NULL);
ret = new_Back_cmd(ret);
}
if (checkChar(beg, end, ';')) {
getToken(beg, end, NULL, NULL);
cmd_p left = ret;
if (left == NULL) parse_errcode++;
cmd_p right = parseline(beg, end);
ret = new_List_cmd(left, right);
}
return ret;
}
static void ter_String(cmd_p root) {
if (root == NULL) return;
list_cmd *lcmd;
exec_cmd *ecmd;
pipe_cmd *pcmd;
back_cmd *bcmd;
redir_cmd *rcmd;
int cur_arg = 0;
switch (root->type) {
case BLOCK:
ter_String(((block_cmd *)root)->subcmd);
break;
case LIST:
lcmd = (list_cmd *)root;
ter_String(lcmd->left);
ter_String(lcmd->right);
break;
case PIPE:
pcmd = (pipe_cmd *)root;
ter_String(pcmd->left);
ter_String(pcmd->right);
break;
case REDIR:
rcmd = (redir_cmd *)root;
ter_String(rcmd->cmd);
*(rcmd->filee) = 0;
break;
case BACK:
bcmd = (back_cmd *)root;
ter_String(bcmd->back);
break;
case EXEC:
ecmd = (exec_cmd *)root;
while (ecmd->largs[cur_arg] != NULL) {
*(ecmd->rargs[cur_arg]) = 0;
++cur_arg;
}
break;
}
}
cmd_p parsecmd(char* line) {
char* beg = line, *end = line + strlen(line);
cmd_p ret = parseline(&beg, end);
if (parse_errcode) {
fprintf(stderr, "Invalid Command\n");
freeTree(ret);
return NULL;
} else {
ter_String(ret);
#ifdef DEBUG_PRINT
printAST(ret, 0);
#endif
return ret;
}
}
cmd_p new_Exec_cmd() {
exec_cmd *ret = (exec_cmd *)malloc(sizeof(exec_cmd));
ret->type = EXEC;
return (cmd_p)ret;
}
cmd_p new_Pipe_cmd(cmd_p left, cmd_p right) {
pipe_cmd *ret = (pipe_cmd *)malloc(sizeof(pipe_cmd));
ret->type = PIPE;
ret->left = left;
ret->right = right;
return (cmd_p)ret;
}
cmd_p new_Redir_cmd(cmd_p subcmd, char* bfile, char* efile, int mode,
int fd) {
redir_cmd *ret = (redir_cmd *)malloc(sizeof(redir_cmd));
ret->type = REDIR;
ret->cmd = subcmd;
ret->fileb = bfile;
ret->filee = efile;
ret->mode = mode;
ret->fd = fd;
return (cmd_p)ret;
}
cmd_p new_Back_cmd(cmd_p subcmd) {
back_cmd *ret = (back_cmd *)malloc(sizeof(back_cmd));
ret->type = BACK;
ret->back = subcmd;
return (cmd_p)ret;
}
cmd_p new_List_cmd(cmd_p left, cmd_p right) {
list_cmd *ret = (list_cmd *)malloc(sizeof(list_cmd));
ret->type = LIST;
ret->left = left;
ret->right = right;
return (cmd_p)ret;
}
cmd_p new_Block_cmd(cmd_p subcmd) {
block_cmd *ret = (block_cmd *)malloc(sizeof(block_cmd));
ret->type = BLOCK;
ret->subcmd = subcmd;
return (cmd_p)ret;
}