Пример #1
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;
}
Пример #2
0
//parses a SIMPLE statement, returning command struct
//modifies global variable t
CMD *simple()
{
	CMD *cmd;
	cmd = mallocCMD();
	cmd->type = SIMPLE;
	while (t && cmd != NULL)
	{
		if (t->type == SIMPLE)
		{
			(cmd->argc)++;
			cmd->argv = realloc(cmd->argv, sizeof(char*) 
				* (cmd->argc + 1));
			cmd->argv[cmd->argc] = 0;
			cmd->argv[cmd->argc - 1] = malloc(strlen(t->text) + 1);
			strcpy(cmd->argv[cmd->argc - 1], t->text);
			t = t->next;
		}
		else if (ISREDOUT(t->type) || ISREDIN(t->type))
			cmd = redirect(cmd);
		else 
			break;
	}
	if (!cmd || !cmd->argc)
		return 0;
	else
		return cmd;
}
Пример #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;
}
Пример #4
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;
}