Пример #1
0
static int dag_parse_variable(struct lexer *bk, struct dag_node *n)
{
	struct token *t = lexer_next_token(bk);
	char mode       = t->lexeme[0];            //=, or + (assign or append)
	lexer_free_token(t);

	t = lexer_next_token(bk);
	if(t->type != TOKEN_LITERAL)
	{
		lexer_report_error(bk, "Literal variable name expected.");
	}

	char *name = xxstrdup(t->lexeme);
	lexer_free_token(t);

	t = lexer_next_token(bk);
	if(t->type != TOKEN_LITERAL)
	{
		lexer_report_error(bk, "Expected LITERAL token, got: %s\n", lexer_print_token(t));
	}

	char *value = xxstrdup(t->lexeme);
	lexer_free_token(t);

	struct hash_table *current_table;
	int nodeid;
	if(n)
	{
		current_table = n->variables;
		nodeid        = n->nodeid;
	}
	else
	{
		current_table = bk->d->variables;
		nodeid        = bk->d->nodeid_counter;
	}

	int result = 1;
	switch(mode)
	{
	case '=':
		dag_variable_add_value(name, current_table, nodeid, value);
		debug(D_MAKEFLOW_PARSER, "%s appending to variable name=%s, value=%s", (n ? "node" : "dag"), name, value);
		break;
	case '+':
		dag_parse_append_variable(bk, nodeid, n, name, value);
		debug(D_MAKEFLOW_PARSER, "%s variable name=%s, value=%s", (n ? "node" : "dag"), name, value);
		break;
	default:
		lexer_report_error(bk, "Unknown variable operator.");
		result = 0;
	}

	dag_parse_process_special_variable(bk, n, nodeid, name, value);

	free(name);
	free(value);

	return result;
}
Пример #2
0
int lexer_read_command(struct lexer *lx)
{
	struct list *tokens = lexer_read_command_aux(lx);

	struct token *t;

	if(list_size(tokens) < 2) {
		/* If the only token in the list is a NEWLINE, then this is an empty line. */
		while((t = list_pop_head(tokens)))
			lexer_free_token(t);

		list_delete(tokens);
		return 1;
	}

	/* Add command start marker.*/
	lexer_push_token(lx, lexer_pack_token(lx, TOKEN_COMMAND));


	/* Merge command tokens into main queue. */
	/* First merge command modifiers, if any. */
	list_first_item(tokens);
	while((t = list_peek_head(tokens))) {
		if(t->type == TOKEN_LITERAL &&
		   ((strcmp(t->lexeme, "LOCAL")    == 0) ||
			(strcmp(t->lexeme, "MAKEFLOW") == 0)    )) {
			t = list_pop_head(tokens);
			lexer_push_token(lx, t);
		} else if(t->type == TOKEN_SPACE) {
			//Discard spaces between modifiers.
			t = list_pop_head(tokens);
			lexer_free_token(t);
		} else {
			break;
		}
	}

	/* Mark end of modifiers. */
	lexer_push_token(lx, lexer_pack_token(lx, TOKEN_COMMAND_MOD_END));

	/* Now merge tha actual command tokens */

	/* Gives the number of actual command tokens, not taking into account command modifiers. */
	int count = 0;

	while((t = list_pop_head(tokens))) {
		count++;
		lexer_push_token(lx, t);
	}

	list_delete(tokens);

	if(count < 1)
		lexer_report_error(lx, "Command is empty.\n");

	return count;
}
Пример #3
0
static int dag_parse_node_nested_makeflow(struct lexer *bk, struct dag_node *n)
{
	struct token *t, *start;

	dag_parse_drop_spaces(bk);

	//Get the dag's file name.
	t = lexer_next_token(bk);

	if(t->type == TOKEN_LITERAL) {
		n->makeflow_dag = xxstrdup(t->lexeme);
		start = t;
	} else {
		lexer_report_error(bk, "At least the name of the Makeflow file should be specified in a recursive call.\n");
		return 0; // not reached, silences warning
	}

	dag_parse_drop_spaces(bk);

	//Get dag's working directory.
	t = lexer_peek_next_token(bk);
	if(t->type == TOKEN_LITERAL) {
		t = lexer_next_token(bk);
		n->makeflow_cwd = xxstrdup(t->lexeme);
		lexer_free_token(t);
	} else {
		n->makeflow_cwd = xxstrdup(".");
	}

	dag_parse_drop_spaces(bk);

	//Get wrapper's name
	char *wrapper = NULL;
	t = lexer_peek_next_token(bk);
	if(t->type == TOKEN_LITERAL) {
		wrapper = xxstrdup(t->lexeme);
		lexer_free_token(t);
	} else {
		wrapper = xxstrdup("");
	}

	free(start->lexeme);
	start->lexeme = string_format("cd %s && %s %s %s",
							  n->makeflow_cwd,
							  wrapper,
							  "makeflow",
							  n->makeflow_dag);
	free(wrapper);

	dag_parse_drop_spaces(bk);
	lexer_preppend_token(bk, start);

	return dag_parse_node_regular_command(bk, n);
}
Пример #4
0
static int dag_parse_node_command(struct lexer *bk, struct dag_node *n)
{
	struct token *t;

	//Jump COMMAND token.
	t = lexer_next_token(bk);
	lexer_free_token(t);

	char *local = dag_variable_lookup_string("BATCH_LOCAL", bk->environment);
	if(local) {
		if(string_istrue(local))
			n->local_job = 1;
		free(local);
	}

	/* Read command modifiers. */
	while((t = lexer_peek_next_token(bk)) && t->type != TOKEN_COMMAND_MOD_END)
	{
		t = lexer_next_token(bk);

		if(strcmp(t->lexeme, "LOCAL") == 0)
		{
			n->local_job = 1;
		}
		else if(strcmp(t->lexeme, "MAKEFLOW") == 0)
		{
			n->nested_job = 1;
		}
		else
		{
			lexer_report_error(bk, "Parser does not know about modifier: %s.\n", t->lexeme);
		}

		lexer_free_token(t);
	}

	if(!t)
	{
		lexer_report_error(bk, "Malformed command.");
	}

	//Free COMMAND_MOD_END token.
	t = lexer_next_token(bk);
	lexer_free_token(t);

	if(n->nested_job)
	{
		return dag_parse_node_nested_makeflow(bk, n);
	}
	else
	{
		return dag_parse_node_regular_command(bk, n);
	}
}
Пример #5
0
static int dag_parse_export(struct lexer *bk)
{
	struct token *t, *vtoken, *vname;

	const char *name;

	int count = 0;
	while((t = lexer_peek_next_token(bk)) && t->type != TOKEN_NEWLINE)
	{
		switch(t->type)
		{
		case TOKEN_VARIABLE:
			vtoken = lexer_next_token(bk);     //Save VARIABLE token.
			vname  = lexer_peek_next_token(bk);
			if(vname->type == TOKEN_LITERAL) {
				name = xxstrdup(vname->lexeme);
			} else {
				lexer_report_error(bk, "Variable definition has name missing.\n");
			}
			lexer_preppend_token(bk, vtoken);  //Restore VARIABLE token.
			dag_parse_variable(bk, NULL);

			break;
		case TOKEN_LITERAL:
			t = lexer_next_token(bk);
			name = xxstrdup(t->lexeme);
			lexer_free_token(t);

			break;
		default:
			lexer_report_error(bk, "Malformed export syntax.\n");
			break;
		}

		set_insert(bk->d->export_vars, name);
		count++;
		debug(D_MAKEFLOW_PARSER, "export variable: %s", name);
	}

	if(t) {
		//Free newline
		t = lexer_next_token(bk);
		lexer_free_token(t);
	}

	if(count < 1) {
		lexer_report_error(bk, "The export syntax needs the explicit name of the variables to be exported.\n");
	}

	return 1;
}
Пример #6
0
struct list *lexer_read_command_aux(struct lexer *lx)
{
	int spaces_deleted = lexer_discard_white_space(lx);

	struct list *tokens = list_create();

	//Preserve space in substitutions.
	if(spaces_deleted && lx->depth > 0) {
		list_push_tail(tokens, lexer_pack_token(lx, TOKEN_SPACE));
	}

	/* Read all command tokens. Note that we read from lx, but put in lx_c. */
	while(1) {
		struct token *t = lexer_read_command_argument(lx);
		if(!t)
			break;

		if(t->type == TOKEN_SUBSTITUTION) {
			tokens = list_splice(tokens, lexer_expand_substitution(lx, t, lexer_read_command_aux));
			lexer_free_token(t);
			continue;
		} else {
			list_push_tail(tokens, t);
			if(t->type==TOKEN_NEWLINE) break;
		}
	}

	return tokens;
}
Пример #7
0
struct token *lexer_next_token(struct lexer_book *bk, struct dag_lookup_set *s)
{
    struct token *head;
    if(list_size(bk->token_queue) == 0) {
        if(bk->eof)
            return NULL;

        lexer_read_line(bk);
        return lexer_next_token(bk, s);
    }

    head = list_pop_head(bk->token_queue);

    if(head->type == SUBSTITUTION) {
        char *substitution = dag_lookup(head->lexeme, s);
        struct lexer_book *bk_s;

        if(!substitution) {
            debug(D_NOTICE, "Variable %s has not yet been defined at line %d.\n", head->lexeme, bk->line_number);
            return lexer_next_token(bk, s);
        }

        bk_s = lexer_init_book(STRING, dag_lookup(head->lexeme, s), bk->line_number, bk->column_number);

        lexer_append_all_tokens(bk, bk_s);

        lexer_free_book(bk_s);
        lexer_free_token(head);

        head = list_pop_head(bk->token_queue);
    }

    return head;
}
Пример #8
0
void dag_parse_drop_spaces(struct lexer *bk)
{
	struct token *t;

	while((t = lexer_peek_next_token(bk)) && t->type == TOKEN_SPACE) {
		t = lexer_next_token(bk);
		lexer_free_token(t);
	}
}
Пример #9
0
void lexer_concatenate_consecutive_literals(struct list *tokens)
{
	struct list *tmp = list_create();
	struct token *t, *prev  = NULL;

	list_first_item(tokens);
	while((t = list_pop_head(tokens))) {
		if(t->type != TOKEN_LITERAL) {
			list_push_tail(tmp, t);
			continue;
		}

		prev = list_pop_tail(tmp);

		if(!prev) {
			list_push_tail(tmp, t);
			continue;
		}

		if(prev->type != TOKEN_LITERAL) {
			list_push_tail(tmp, prev);
			list_push_tail(tmp, t);
			continue;
		}

		char *merge = string_format("%s%s", prev->lexeme, t->lexeme);
		lexer_free_token(t);
		free(prev->lexeme);
		prev->lexeme = merge;

		list_push_tail(tmp, prev);
	}

	/* Copy to tokens, drop spaces. */
	list_first_item(tmp);
	while((t = list_pop_head(tmp)))
		if(t->type != TOKEN_SPACE) {
			list_push_tail(tokens, t);
		} else {
			lexer_free_token(t);
		}

	list_delete(tmp);
}
Пример #10
0
static int dag_parse_node(struct lexer *bk)
{
	struct token *t = lexer_next_token(bk);
	if(t->type != TOKEN_FILES)
	{
		lexer_report_error(bk, "Error reading rule.");
	}
	lexer_free_token(t);

	struct dag_node *n;
	n = dag_node_create(bk->d, bk->line_number);

	if(verbose_parsing && bk->d->nodeid_counter % parsing_rule_mod_counter == 0)
	{
		fprintf(stdout, "\rRules parsed: %d", bk->d->nodeid_counter + 1);
		fflush(stdout);
	}

	n->category = bk->category;
	list_push_tail(n->category->nodes, n);

	dag_parse_node_filelist(bk, n);

	bk->environment->node = n;

	/* Read variables, if any */
	while((t = lexer_peek_next_token(bk)) && t->type != TOKEN_COMMAND)
	{
		switch (t->type) {
		case TOKEN_VARIABLE:
			dag_parse_variable(bk, n);
			break;
		default:
			lexer_report_error(bk, "Expected COMMAND or VARIABLE, got: %s", lexer_print_token(t));
			break;
		}
	}

	if(!t)
	{
		lexer_report_error(bk, "Rule does not have a command.\n");
	}

	dag_parse_node_command(bk, n);
	bk->environment->node = NULL;

	n->next = bk->d->nodes;
	bk->d->nodes = n;
	itable_insert(bk->d->node_table, n->nodeid, n);

	debug(D_MAKEFLOW_PARSER, "Setting resource category '%s' for rule %d.\n", n->category->label, n->nodeid);
	dag_node_fill_resources(n);
	dag_node_print_debug_resources(n);

	return 1;
}
Пример #11
0
static int dag_parse_syntax(struct lexer *bk)
{
	struct token *t = lexer_next_token(bk);

	if(strcmp(t->lexeme, "export") == 0) {
		lexer_free_token(t);
		dag_parse_export(bk);
	} else {
		lexer_report_error(bk, "Unknown syntax keyboard.\n");
	}


	return 1;
}
Пример #12
0
static int dag_parse(struct dag *d, FILE *stream)
{
	struct lexer *bk = lexer_create(STREAM, stream, 1, 1);

	bk->d        = d;
	bk->stream   = stream;
	bk->category = dag_task_category_lookup_or_create(d, "default");

	struct dag_variable_lookup_set s = { d, NULL, NULL, NULL };
	bk->environment = &s;

	struct token *t;

	while((t = lexer_peek_next_token(bk)))
	{
		s.category = bk->category;
		s.node     = NULL;
		s.table    = NULL;

		switch (t->type) {
		case TOKEN_NEWLINE:
		case TOKEN_SPACE:
			/* Skip newlines, spaces at top level. */
			lexer_free_token(lexer_next_token(bk));
			break;
		case TOKEN_SYNTAX:
			dag_parse_syntax(bk);
			break;
		case TOKEN_FILES:
			dag_parse_node(bk);
			break;
		case TOKEN_VARIABLE:
			dag_parse_variable(bk, NULL);
			break;
		default:
			lexer_report_error(bk, "Unexpected token. Expected one of NEWLINE, SPACE, SYNTAX, FILES, or VARIABLE, but got: %s\n:", lexer_print_token(t));
			break;
		}
	}

	dag_close_over_environment(d);
	dag_compile_ancestors(d);
	free(bk);

	return 1;
}
Пример #13
0
void                    lexer_free(s_lexer              *lexer)
{
  s_token_list          *token_list = NULL;
  s_token_list          *token_list_next = NULL;

  if (lexer == NULL)
    return;

  token_list = lexer->token_list;

  while (token_list != NULL)
  {
    token_list_next = token_list->next;
    lexer_free_token(token_list->token);
    mfree(token_list);
    token_list = token_list_next;
  }

  mfree(lexer);
}
Пример #14
0
static int dag_parse_node_regular_command(struct lexer *bk, struct dag_node *n)
{
	struct buffer b;

	buffer_init(&b);

	struct token *t;
	while((t = lexer_next_token(bk)) && t->type != TOKEN_NEWLINE)
	{
		switch(t->type)
		{
		case TOKEN_SPACE:
			buffer_printf(&b, " ");
			break;
		case TOKEN_LITERAL:
			buffer_printf(&b, "%s", t->lexeme);
			break;
		case TOKEN_IO_REDIRECT:
			buffer_printf(&b, "%s", t->lexeme);
			break;
		default:
			lexer_report_error(bk, "Unexpected command token: %s.\n", lexer_print_token(t));
			break;
		}

		lexer_free_token(t);
	}

	if(!t)
	{
		lexer_report_error(bk, "Command does not end with newline.\n");
	}

	n->command = xxstrdup(buffer_tostring(&b));

	buffer_free(&b);

	debug(D_MAKEFLOW_PARSER, "node command=%s", n->command);

	return 1;
}
Пример #15
0
struct token *lexer_concat_expandable(struct lexer *lx, struct list *tokens)
{
	struct token *t;

	struct buffer b;
	buffer_init(&b);

	char *substitution;

	list_first_item(tokens);

	while((t = list_pop_head(tokens))) {
		switch(t->type) {
		case TOKEN_SUBSTITUTION:
			substitution = dag_variable_lookup_string(t->lexeme, lx->environment);
			if(!substitution)
				fatal("Variable %s has not yet been defined at line % " PRId64 ".\n", t->lexeme, lx->line_number);
			buffer_printf(&b, "%s", substitution);
			free(substitution);
			break;
		case TOKEN_LITERAL:
			if(strcmp(t->lexeme, "") != 0)           // Skip empty strings.
				buffer_printf(&b, "%s", t->lexeme);
			break;
		default:
			lexer_report_error(lx, "Error in expansion, got: %s.\n", lexer_print_token(t));
			break;
		}

		lexer_free_token(t);
	}

	t = lexer_pack_token(lx, TOKEN_LITERAL);
	t->lexeme = xxstrdup(buffer_tostring(&b));
	buffer_free(&b);

	return t;
}
Пример #16
0
struct list *lexer_read_file_list_aux(struct lexer *lx)
{
	struct list *tokens = list_create();

	lexer_discard_white_space(lx);

	while(1) {
		struct token *t = lexer_read_file(lx);
		if(!t) break;

		//Do substitution recursively
		if(t->type == TOKEN_SUBSTITUTION) {
			tokens = list_splice(tokens, lexer_expand_substitution(lx, t, lexer_read_file_list_aux));
			lexer_free_token(t);
			continue;
		} else {
			list_push_tail(tokens, t);
			if(t->type==TOKEN_NEWLINE) break;
		}
	}

	return tokens;
}
Пример #17
0
static int dag_parse_node_filelist(struct lexer *bk, struct dag_node *n)
{
	int before_colon = 1;

	char *filename;
	char *newname;

	struct token *t, *arrow, *rename;
	while((t = lexer_next_token(bk)))
	{
		filename = NULL;
		newname  = NULL;

		switch (t->type) {
		case TOKEN_COLON:
			before_colon = 0;
			lexer_free_token(t);
			break;
		case TOKEN_NEWLINE:
			/* Finished reading file list */
			lexer_free_token(t);
			return 1;
			break;
		case TOKEN_LITERAL:
			rename = NULL;
			arrow = lexer_peek_next_token(bk);
			if(!arrow)
			{
				lexer_report_error(bk, "Rule specification is incomplete.");
			}
			else if(arrow->type == TOKEN_REMOTE_RENAME)        //Is the arrow really an arrow?
			{
				lexer_free_token(lexer_next_token(bk));  //Jump arrow.
				rename = lexer_next_token(bk);
				if(!rename)
				{
					lexer_report_error(bk, "Remote name specification is incomplete.");
				}
			}

			filename = t->lexeme;
			newname  = rename ? rename->lexeme : NULL;

			if(before_colon)
				dag_node_add_target_file(n, filename, newname);
			else
				dag_node_add_source_file(n, filename, newname);

			lexer_free_token(t);

			if(rename)
			{
				lexer_free_token(rename);
			}

			break;
		default:
			lexer_report_error(bk, "Error reading file list. %s", lexer_print_token(t));
			break;
		}

	}

	return 0;
}