int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args)
{
	struct cil_symtab_datum *user_datum = NULL;
	struct cil_symtab_datum *role_datum = NULL;
	struct cil_symtab_datum *type_datum = NULL;
	struct cil_tree_node *node = NULL;
	struct cil_symtab_datum *lvlrange_datum = NULL;

	int rc = SEPOL_ERR;

	rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(user_datum);

	if (node->flavor != CIL_USER) {
		cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
		rc = SEPOL_ERR;
		goto exit;
	}

	context->user = (struct cil_user*)user_datum;

	rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(role_datum);
	if (node->flavor != CIL_ROLE) {
		rc = SEPOL_ERR;
		cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
		goto exit;
	}

	context->role = (struct cil_role*)role_datum;

	rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(type_datum);

	if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
		rc = SEPOL_ERR;
		cil_log(CIL_ERR, "Type not a type or type alias\n");
		goto exit;
	}
	context->type = type_datum;

	if (context->range_str != NULL) {
		rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
		if (rc != SEPOL_OK) {
			goto exit;
		}
		context->range = (struct cil_levelrange*)lvlrange_datum;

		/* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/
		if (context->range->datum.name == NULL) {
			rc = cil_resolve_levelrange(current, context->range, extra_args);
			if (rc != SEPOL_OK) {
				goto exit;
			}
		}
	} else if (context->range != NULL) {
		rc = cil_resolve_levelrange(current, context->range, extra_args);
		if (rc != SEPOL_OK) {
			goto exit;
		}
	}

	return SEPOL_OK;

exit:
	return rc;
}
int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args)
{
	struct cil_symtab_datum *user_datum = NULL;
	struct cil_symtab_datum *role_datum = NULL;
	struct cil_symtab_datum *type_datum = NULL;
	struct cil_tree_node *node = NULL;
	struct cil_symtab_datum *lvlrange_datum = NULL;

	int rc = SEPOL_ERR;

	rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(user_datum);

	if (node->flavor != CIL_USER) {
		cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
		rc = SEPOL_ERR;
		goto exit;
	}

	context->user = (struct cil_user*)user_datum;

	rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(role_datum);
	if (node->flavor != CIL_ROLE) {
		rc = SEPOL_ERR;
		cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
		goto exit;
	}

	context->role = (struct cil_role*)role_datum;

	rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
	if (rc != SEPOL_OK) {
		goto exit;
	}

	node = NODE(type_datum);

	if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
		rc = SEPOL_ERR;
		cil_log(CIL_ERR, "Type not a type or type alias\n");
		goto exit;
	}
	context->type = type_datum;

	if (context->range_str != NULL) {
		rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
		if (rc != SEPOL_OK) {
			goto exit;
		}
		context->range = (struct cil_levelrange*)lvlrange_datum;

		 
		if (context->range->datum.name == NULL) {
			rc = cil_resolve_levelrange(current, context->range, extra_args);
			if (rc != SEPOL_OK) {
				goto exit;
			}
		}
	} else if (context->range != NULL) {
		rc = cil_resolve_levelrange(current, context->range, extra_args);
		if (rc != SEPOL_OK) {
			goto exit;
		}
	}

	return SEPOL_OK;

exit:
	return rc;
}