int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
	enum cil_syntax syntax[] = {
		CIL_SYN_STRING,
		CIL_SYN_STRING,
		CIL_SYN_STRING,
		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
		CIL_SYN_END
	};
	int syntax_len = sizeof(syntax)/sizeof(*syntax);
	int rc = SEPOL_ERR;
	struct cil_filecon *filecon = NULL;
	char *type = NULL;

	if (db == NULL || parse_current == NULL || ast_node == NULL) {
		goto exit;
	}

	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	type = parse_current->next->next->data;
	cil_filecon_init(&filecon);

	filecon->path_str = parse_current->next->data;

	if (type == CIL_KEY_FILE) {
		filecon->type = CIL_FILECON_FILE;
	} else if (type == CIL_KEY_DIR) {
		filecon->type = CIL_FILECON_DIR;
	} else if (type == CIL_KEY_CHAR) {
		filecon->type = CIL_FILECON_CHAR;
	} else if (type == CIL_KEY_BLOCK) {
		filecon->type = CIL_FILECON_BLOCK;
	} else if (type == CIL_KEY_SOCKET) {
		filecon->type = CIL_FILECON_SOCKET;
	} else if (type == CIL_KEY_PIPE) {
		filecon->type = CIL_FILECON_PIPE;
	} else if (type == CIL_KEY_SYMLINK) {
		filecon->type = CIL_FILECON_SYMLINK;
	} else if (type == CIL_KEY_ANY) {
		filecon->type = CIL_FILECON_ANY;
	} else {
		cil_log(CIL_ERR, "Invalid file type\n");
		rc = SEPOL_ERR;
		goto exit;
	}

	if (parse_current->next->next->next->cl_head == NULL) {
		filecon->context_str = parse_current->next->next->next->data;
	} else {
		if (parse_current->next->next->next->cl_head->next == NULL) {
			filecon->context = NULL;
		} else {
			cil_context_init(&filecon->context);

			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
			if (rc != SEPOL_OK) {
				goto exit;
			}
		}
	}

	ast_node->data = filecon;
	ast_node->flavor = CIL_FILECON;

	return SEPOL_OK;

exit:
	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
	cil_destroy_filecon(filecon);
	return rc;
}
int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
	enum cil_syntax syntax[] = {
		CIL_SYN_STRING,
		CIL_SYN_STRING,
		CIL_SYN_STRING,
		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
		CIL_SYN_END
	};
	int syntax_len = sizeof(syntax)/sizeof(*syntax);
	int rc = SEPOL_ERR;
	struct cil_filecon *filecon = NULL;
	char *type = NULL;

	if (db == NULL || parse_current == NULL || ast_node == NULL) {
		goto exit;
	}

	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	type = parse_current->next->next->data;
	cil_filecon_init(&filecon);

	filecon->path_str = parse_current->next->data;

	if (type == CIL_KEY_FILE) {
		filecon->type = CIL_FILECON_FILE;
	} else if (type == CIL_KEY_DIR) {
		filecon->type = CIL_FILECON_DIR;
	} else if (type == CIL_KEY_CHAR) {
		filecon->type = CIL_FILECON_CHAR;
	} else if (type == CIL_KEY_BLOCK) {
		filecon->type = CIL_FILECON_BLOCK;
	} else if (type == CIL_KEY_SOCKET) {
		filecon->type = CIL_FILECON_SOCKET;
	} else if (type == CIL_KEY_PIPE) {
		filecon->type = CIL_FILECON_PIPE;
	} else if (type == CIL_KEY_SYMLINK) {
		filecon->type = CIL_FILECON_SYMLINK;
	} else if (type == CIL_KEY_ANY) {
		filecon->type = CIL_FILECON_ANY;
	} else {
		cil_log(CIL_ERR, "Invalid file type\n");
		rc = SEPOL_ERR;
		goto exit;
	}

	if (parse_current->next->next->next->cl_head == NULL) {
		filecon->context_str = parse_current->next->next->next->data;
	} else {
		if (parse_current->next->next->next->cl_head->next == NULL) {
			filecon->context = NULL;
		} else {
			cil_context_init(&filecon->context);

			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
			if (rc != SEPOL_OK) {
				goto exit;
			}
		}
	}

	ast_node->data = filecon;
	ast_node->flavor = CIL_FILECON;

	return SEPOL_OK;

exit:
	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
	cil_destroy_filecon(filecon);
	return rc;
}