/** Return the attribute number of an attribute reference
 *
 */
static ssize_t xlat_attr_num(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
			     UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
			     REQUEST *request, char const *fmt)
{
	VALUE_PAIR *vp;

	fr_skip_spaces(fmt);

	if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;

	*out = talloc_typed_asprintf(ctx, "%i", vp->da->attr);
	return talloc_array_length(*out) - 1;
}
/** Return the vendor number of an attribute reference
 *
 */
static ssize_t xlat_vendor_num(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
			       UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
			       REQUEST *request, char const *fmt)
{
	VALUE_PAIR *vp;

	while (isspace((int) *fmt)) fmt++;

	if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;

	*out = talloc_typed_asprintf(ctx, "%i", fr_dict_vendor_num_by_da(vp->da));
	return talloc_array_length(*out) - 1;
}
/** Return the attribute name of an attribute reference
 *
 */
static ssize_t xlat_attr(TALLOC_CTX *ctx, char **out, size_t outlen,
			 UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
			 REQUEST *request, char const *fmt)
{
	VALUE_PAIR *vp;

	fr_skip_spaces(fmt);

	if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;
	strlcpy(*out, vp->da->name, outlen);

	*out = talloc_typed_strdup(ctx, vp->da->name);
	return talloc_array_length(*out) - 1;
}
static ssize_t xlat_date_convert(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
				 void const *mod_inst, UNUSED void const *xlat_inst,
				 REQUEST *request, char const *fmt)
{
	rlm_date_t const *inst = mod_inst;
	struct tm tminfo;
	struct timeval now;
	VALUE_PAIR *vp;

	memset(&tminfo, 0, sizeof(tminfo));

	if (strcmp(fmt, "request") == 0) {
		return date_encode_strftime(out, outlen, inst, request,
					    request->packet->timestamp.tv_sec);
	}

	if (strcmp(fmt, "now") == 0) {
		gettimeofday(&now, NULL);
		return date_encode_strftime(out, outlen, inst, request, now.tv_sec);
	}

	if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;

	switch (vp->vp_type) {
	/*
	 *	These are 'to' types, i.e. we'll convert the integers
	 *	to a time structure, and then output it in the specified
	 *	format as a string.
	 */
	case FR_TYPE_DATE:
		return date_encode_strftime(out, outlen, inst, request, vp->vp_date);

	case FR_TYPE_UINT32:
	case FR_TYPE_UINT64:
		return date_encode_strftime(out, outlen, inst, request, (time_t) vp->vp_uint32);

	/*
	 *	These are 'from' types, i.e. we'll convert the input string
	 *	into a time structure, and then output it as an integer
	 *	unix timestamp.
	 */
	case FR_TYPE_STRING:
		return date_convert_string(request, out, outlen, vp->vp_strvalue, inst->fmt);

	default:
		REDEBUG("Can't convert type %s into date", fr_int2str(fr_value_box_type_names, vp->da->type, "<INVALID>"));
	}

	return -1;
}
/** Return the vendor of an attribute reference
 *
 */
static ssize_t xlat_vendor(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
			   UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
			   REQUEST *request, char const *fmt)
{
	VALUE_PAIR *vp;
	fr_dict_vendor_t const *vendor;

	fr_skip_spaces(fmt);

	if ((xlat_fmt_get_vp(&vp, request, fmt) < 0) || !vp) return 0;

	vendor = fr_dict_vendor_by_da(vp->da);
	if (!vendor) return 0;

	*out = talloc_typed_strdup(ctx, vendor->name);
	return talloc_array_length(*out) - 1;
}