Exemplo n.º 1
0
//parses an and-or statement, returning command struct
//modifies global variable t
CMD *andOr()
{
	CMD *cmd = 0 /*output*/, *tmp = 0; //swap
	cmd = pipeline();
	while (t && (t->type == SEP_AND || t->type == SEP_OR))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = andOr();
		if (!cmd->right)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
	}
	return cmd;
}
Exemplo n.º 2
0
//parses a pipeline, returning command struct
//modifies global variable t
CMD *pipeline()
{
	CMD *cmd = 0, *tmp = 0;
	cmd = stage();
	while (t && ISPIPE(t->type))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		if (cmd->toType != NONE)
		{
			DIE("Parse: two output redirects\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = pipeline();
		if (!cmd->right)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
	}
	return cmd;
}
Exemplo n.º 3
0
//handles redirect statements for stage and simple
//input is a command struct, output is same struct with changed i/o
CMD *redirect(CMD* cmd)
{
	if (ISREDOUT(t->type))
	{
		if (cmd->toType != NONE)
		{
			DIE("Parse: two output redirects\n");
			freeCMD(cmd);
			return 0;
		}
		cmd->toType = t->type;
		t = t->next;
		if (!t || t->type != SIMPLE)
		{
			DIE("Parse: missing filename\n");
			freeCMD(cmd);
			return 0;
		}
		cmd->toFile = malloc(strlen(t->text) + 1);
		strcpy(cmd->toFile, t->text);
		t = t->next;
	}
	else if (t->type == RED_IN || t->type == RED_HERE)
	{
		if (cmd->fromType != NONE)
		{
			DIE("Parse: two input redirects\n");
			freeCMD(cmd);
			return 0;
		}
		cmd->fromType = t->type;
		t = t->next;
		if (!t || t->type != SIMPLE)
		{
			DIE("Parse: missing filename\n");
			freeCMD(cmd);
			return 0;
		}
		if (cmd->fromType == RED_IN)
		{
			cmd->fromFile = malloc(strlen(t->text) + 1);
			strcpy(cmd->fromFile, t->text);
		}
		else
		{
			cmd->fromFile = hereDoc(t->text);
		}
		t = t->next;
	}
	return cmd;
}
Exemplo n.º 4
0
//parses a stage, returning a command struct
//modifies global variable t
CMD *stage()
{
	CMD *tmp;
	CMD *cmd = 0;
	if (!t)
		return 0;
	tmp = mallocCMD();
	while (t && (ISREDOUT(t->type) || ISREDIN(t->type)))
		tmp = redirect(tmp);
	if (!tmp)
		return 0;
	else if (!t)
	{
		DIE("Parse: null command\n");
		return 0;
	}
	else if (t->type == PAR_LEFT)
	{
		cmd = mallocCMD();
		cmd->type = SUBCMD;
		t = t->next;
		cmd->left = command();
		if (!cmd->left)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		else if (!t || t->type != PAR_RIGHT)
		{
			DIE("Parse: unbalanced parens\n");
			freeCMD(cmd);
			return 0;
		}
		else 
		{
			t = t->next;
			while(t && cmd && (ISREDOUT(t->type) 
				|| ISREDIN(t->type)))
				cmd = redirect(cmd);
		}
	}
	else
		cmd = simple();
	cmd = merge(cmd, tmp);
	freeCMD(tmp);
	return cmd;
}
Exemplo n.º 5
0
CMD *parseSimple(token **lstHead)
{
	CMD *cmd = mallocCMD();
	while((*lstHead) && ((*lstHead)->type == SIMPLE || IS_RED((*lstHead)->type)))
	{
		cmd->type = SIMPLE;
		if((*lstHead)->type == SIMPLE)
		{
			//not a redirection
			cmd->argv[cmd->argc] = copyText((*lstHead)->text);
			cmd->argc++;
			cmd->argv = realloc(cmd->argv,(cmd->argc+1)*sizeof(char*));
			cmd->argv[cmd->argc] = NULL;
			*lstHead = (*lstHead)->next;
		}
		else
		{
			//redirection found
			cmd = parseRedirect(lstHead,cmd);
			if(cmd->type == ERROR)
			{
				//if error occurred in parseRedirect
				return cmd;
			}
		}			
	}

	if(cmd && cmd->type == NONE)
	{
		//case where no SIMPLE was found
		freeCMD(cmd);
		return NULL;
	}
	return cmd;
}
Exemplo n.º 6
0
CMD* make_cmd(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form command (no tokens)");

    CMD* cmd_tree = make_andor(&list);
    if (cmd_tree->type == ERROR) return cmd_tree;

    int next_type = type(list);
    if (next_type == SEP_END || next_type == SEP_BG) {
        advance(&list);

        CMD* parent = mallocCMD();
        parent->type = next_type;
        parent->left = cmd_tree;
        cmd_tree = parent;

        // See if it is possible to make a subcommand; if not, return to initial
        // state (because subcommand is optional following ; or &
        token_list* old_head = list; // Hold onto a copy in case sub command
                                     // returns an error
        CMD* sub_cmd = make_cmd(&list);
        if (sub_cmd->type == ERROR) {
            freeCMD(sub_cmd);
            sub_cmd = NULL;
            list = old_head;
        }
        cmd_tree->right = sub_cmd;
    }

    *list_ref = list;
    return cmd_tree;
}
Exemplo n.º 7
0
CMD* make_andor(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form and-or (no tokens)");

    CMD* andor_tree = make_pipeline(&list);
    if (andor_tree->type == ERROR) return andor_tree;

    int next_type = type(list);
    if (next_type == SEP_AND || next_type == SEP_OR) {
        advance(&list);

        CMD* parent = mallocCMD(); // TODO: make sure all initialized to NULL
        parent->type = next_type;
        parent->left = andor_tree;
        andor_tree = parent;

        CMD* sub_andor = make_andor(&list);
        if (sub_andor->type == ERROR) {
            freeCMD(andor_tree);
            return sub_andor;
        }
        andor_tree->right = sub_andor;
    }

    *list_ref = list;
    return andor_tree;
}
Exemplo n.º 8
0
CMD* make_pipeline(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form pipeline (no tokens)");

    CMD* pipeline_tree = make_stage(&list);
    if (pipeline_tree->type == ERROR) return pipeline_tree;

    int next_type = type(list);
    if (next_type == PIPE || next_type == PIPE_ERR) {
        advance(&list);

        CMD* parent = mallocCMD();
        parent->type = next_type;
        parent->left = pipeline_tree;
        pipeline_tree = parent;

        CMD* sub_pipeline = make_pipeline(&list);
        if (sub_pipeline->type == ERROR) {
            freeCMD(pipeline_tree);
            return sub_pipeline;
        }
        pipeline_tree->right = sub_pipeline;
    }

    *list_ref = list;
    return pipeline_tree;
}
Exemplo n.º 9
0
/* The top level function of a recursive descent parser for the grammar defined
 * in parse.h. Parses a token list into a command structure.
 *
 * @list = list of tokens to parse
 *
 * Returns: a pointer to the resulting command structure; NULL if errors found
 */
CMD* parse(token_list* list)
{
    CMD* parse_tree = make_cmd(&list);

    if (parse_tree->type == ERROR) {
        assert(parse_tree);
        ERROR(parse_tree->argv[0]);
        freeCMD(parse_tree);
        return NULL;
    }
    if (list) {
        ERROR("could not parse remaining tokens");
        freeCMD(parse_tree);
        return NULL;
    }

    return parse_tree;
}
Exemplo n.º 10
0
CMD *parse(token *list)
{
	CMD *cmd = parseCommand(&list);
	if(cmd->type == ERROR)
	{
		freeCMD(cmd);
		return NULL;
	}
	return cmd;
}
Exemplo n.º 11
0
CMD *errorCMD(CMD *toFree)
{
	if(toFree)
	{
		freeCMD(toFree);
	}
	CMD *cmd = mallocCMD();
	cmd->type = ERROR;
	return cmd;
}
Exemplo n.º 12
0
//takes the i/o commands from cont and puts them in cmd
//returns 0 and sends an error if there is a conflict
CMD *merge(CMD *cmd, CMD* cont)
{
	if (!cmd || !cont)
		return 0;
	if (cont->toType != NONE)
	{
		if (cmd->toType != NONE)
		{
			DIE("Parse: two output redirects\n");
			freeCMD(cmd);
			return 0;
		}
		else
		{
			cmd->toType = cont->toType;
			cmd->toFile = malloc(strlen(cont->toFile) + 1);
			strcpy(cmd->toFile, cont->toFile);
		}
	}
	if (cont->fromType != NONE)
	{
		if (cmd->fromType != NONE)
		{
			DIE("Parse: two input redirects\n");
			freeCMD(cmd);
			return 0;
		}
		else
		{
			cmd->fromType = cont->fromType;
			cmd->fromFile = malloc(strlen(cont->fromFile) + 1);
			strcpy(cmd->fromFile, cont->fromFile);
		}
	}
	return cmd;
}
Exemplo n.º 13
0
//parses a command, returning command struct
//modifies global variable t
CMD *command()
{
	CMD *cmd = 0 /*output*/, *tmp = 0; //swap variable
	cmd = andOr();
	while (t && (t->type == SEP_END || t->type == SEP_BG))
	{
		if (!cmd)
		{
			DIE("Parse: null command\n");
			freeCMD(cmd);
			return 0;
		}
		tmp = cmd;
		cmd = mallocCMD();
		cmd->type = t->type;
		cmd->left = tmp;
		t = t->next;
		cmd->right = command();
	}
	return cmd;
}
Exemplo n.º 14
0
int main(int argc, char** argv)
{
    int nCmd = 1; // Command number
    char *line;   // Initial command line
    token *list;  // Linked list of tokens
    CMD *cmd;     // Parsed command

    for( ; ; free(line))
    {
        // Prompt for command
        printf("(%d)$ ", nCmd);
        fflush(stdout);

        // Read line
        if((line = getLine(stdin)) == NULL)
	    {
            break; // Break on end of file
        }

        // Lex line into tokens
	    if((list = tokenize(line)) == NULL)
        {
            continue;
        }

	    if ((cmd = parse(list)) != NULL) // Parsed command?
        {
            process(cmd); // Execute command
            freeCMD(cmd); // Free associated storage
            nCmd++;       // Adjust prompt
        }

        freeList(list); // Free token list
    }

    return EXIT_SUCCESS;
}
Exemplo n.º 15
0
CMD* make_stage(token_list** list_ref)
{
    token_list* list = *list_ref;
    if (!list) return make_error_cmd("could not form stage (no tokens)");

    CMD* stage_tree = mallocCMD(); // Current type is NONE

    int next_type = NONE; // Hold the type of the head token of list
    bool redir_in = false; // Has there been a previous input redirection?
    bool redir_out = false;

    // Loop until hit a pipe or a separator; raise an error if multiple redirect
    // or both a command and subcommand
    while ((next_type = type(list)) != -1 &&
        !ISSEP(next_type) && !ISPIPE(next_type) && next_type != PAR_RIGHT) {

        bool error = false; // Signals whether the current action results in an
                            // error
        if (next_type == SIMPLE && stage_tree->type != SUBCMD) {
            int argc = stage_tree->argc + 1;
            char** argv = stage_tree->argv;
            argv = realloc(argv, (argc + 1) * sizeof(char*)); // +1 for trailing
                                                              // NULL required
                                                              // by freeCMD
            argv[argc - 1] = strdup(text(list));
            argv[argc] = NULL;
            stage_tree->argc = argc;
            stage_tree->argv = argv;
            stage_tree->type = SIMPLE;
        } else if ((next_type == RED_IN || next_type == RED_HERE)
            && !redir_in) {
            error = make_redirect(stage_tree, &redir_in, next_type, &list);
        } else if (ISREDOUT(next_type) && !redir_out) {
            error = make_redirect(stage_tree, &redir_out, next_type, &list);
        } else if (next_type == PAR_LEFT &&
            stage_tree->type == NONE) { // Can't have two subcommands in a stage

            advance(&list); // Advance past left parentheses

            CMD* subcmd_tree = make_cmd(&list);
            error = subcmd_tree->type == ERROR || type(list) != PAR_RIGHT;

            stage_tree->type = SUBCMD;
            stage_tree->left = subcmd_tree;
        } else {
            error = true;
        }

        if (error) {
            freeCMD(stage_tree);
            return make_error_cmd("Invalid stage");
        }

        advance(&list);
    }

    // Make sure we didn't double-redirect
    if (ISPIPE(next_type) && redir_out) {
        freeCMD(stage_tree);
        return make_error_cmd("Double redirect - pipe and >");
    }

    // Make sure there was actually an argument
    if (stage_tree->type == NONE) {
        freeCMD(stage_tree);
        return make_error_cmd("No arguments for simple command");
    }

    assert(stage_tree->type != NONE);

    *list_ref = list;
    return stage_tree;
}