mprint(struct magic_set *ms, struct magic *m)
{
	uint64_t v;
	float vf;
	double vd;
	int64_t t = 0;
 	char buf[128], tbuf[26], sbuf[512], ebuf[512];
	const char *desc;
	union VALUETYPE *p = &ms->ms_value;

	if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1)
		desc = m->desc;
	else
		desc = ebuf;

#define	PRINTER(value, format, stype, utype)	\
	v = file_signextend(ms, m, CAST(uint64_t, value)); \
	switch (check_fmt(ms, desc)) { \
	case -1: \
		return -1; \
	case 1: \
		if (m->flag & UNSIGNED) { \
			(void)snprintf(buf, sizeof(buf), "%" format "u", \
			    CAST(utype, v)); \
		} else { \
			(void)snprintf(buf, sizeof(buf), "%" format "d", \
			    CAST(stype, v)); \
		} \
		if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \
			return -1; \
		break; \
	default: \
		if (m->flag & UNSIGNED) { \
		       if (file_printf(ms, F(ms, desc, "%" format "u"), \
			   CAST(utype, v)) == -1) \
			   return -1; \
		} else { \
		       if (file_printf(ms, F(ms, desc, "%" format "d"), \
			   CAST(stype, v)) == -1) \
			   return -1; \
		} \
		break; \
	} \
	t = ms->offset + sizeof(stype); \
	break

  	switch (m->type) {
  	case FILE_BYTE:
		PRINTER(p->b, "", int8_t, uint8_t);

  	case FILE_SHORT:
  	case FILE_BESHORT:
  	case FILE_LESHORT:
		PRINTER(p->h, "", int16_t, uint16_t);

  	case FILE_LONG:
  	case FILE_BELONG:
  	case FILE_LELONG:
  	case FILE_MELONG:
		PRINTER(p->l, "", int32_t, uint32_t);
  		break;

  	case FILE_QUAD:
  	case FILE_BEQUAD:
  	case FILE_LEQUAD:
	case FILE_OFFSET:
		PRINTER(p->q, INT64_T_FORMAT, long long, unsigned long long);
  		break;

  	case FILE_STRING:
  	case FILE_PSTRING:
  	case FILE_BESTRING16:
  	case FILE_LESTRING16:
		if (m->reln == '=' || m->reln == '!') {
			if (file_printf(ms, F(ms, desc, "%s"),
			    file_printable(sbuf, sizeof(sbuf), m->value.s,
			    sizeof(m->value.s))) == -1)
				return -1;
			t = ms->offset + m->vallen;
		}
		else {
			char *str = p->s;

			/* compute t before we mangle the string? */
			t = ms->offset + strlen(str);

			if (*m->value.s == '\0')
				str[strcspn(str, "\r\n")] = '\0';

			if (m->str_flags & STRING_TRIM)
				str = file_strtrim(str);
					
			if (file_printf(ms, F(ms, desc, "%s"),
			    file_printable(sbuf, sizeof(sbuf), str,
				sizeof(p->s) - (str - p->s))) == -1)
				return -1;

			if (m->type == FILE_PSTRING) {
				size_t l = file_pstring_length_size(ms, m);
				if (l == FILE_BADSIZE)
					return -1;
				t += l;
			}
		}
		break;

	case FILE_DATE:
	case FILE_BEDATE:
	case FILE_LEDATE:
	case FILE_MEDATE:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_fmttime(tbuf, sizeof(tbuf), p->l, 0)) == -1)
			return -1;
		t = ms->offset + sizeof(uint32_t);
		break;

	case FILE_LDATE:
	case FILE_BELDATE:
	case FILE_LELDATE:
	case FILE_MELDATE:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_fmttime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL)) == -1)
			return -1;
		t = ms->offset + sizeof(uint32_t);
		break;

	case FILE_QDATE:
	case FILE_BEQDATE:
	case FILE_LEQDATE:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_fmttime(tbuf, sizeof(tbuf), p->q, 0)) == -1)
			return -1;
		t = ms->offset + sizeof(uint64_t);
		break;

	case FILE_QLDATE:
	case FILE_BEQLDATE:
	case FILE_LEQLDATE:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_fmttime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1)
			return -1;
		t = ms->offset + sizeof(uint64_t);
		break;

	case FILE_QWDATE:
	case FILE_BEQWDATE:
	case FILE_LEQWDATE:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_fmttime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS))
		    == -1)
			return -1;
		t = ms->offset + sizeof(uint64_t);
		break;

	case FILE_FLOAT:
	case FILE_BEFLOAT:
	case FILE_LEFLOAT:
		vf = p->f;
		switch (check_fmt(ms, desc)) {
		case -1:
			return -1;
		case 1:
			(void)snprintf(buf, sizeof(buf), "%g", vf);
			if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
				return -1;
			break;
		default:
			if (file_printf(ms, F(ms, desc, "%g"), vf) == -1)
				return -1;
			break;
		}
		t = ms->offset + sizeof(float);
  		break;

	case FILE_DOUBLE:
	case FILE_BEDOUBLE:
	case FILE_LEDOUBLE:
		vd = p->d;
		switch (check_fmt(ms, desc)) {
		case -1:
			return -1;
		case 1:
			(void)snprintf(buf, sizeof(buf), "%g", vd);
			if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
				return -1;
			break;
		default:
			if (file_printf(ms, F(ms, desc, "%g"), vd) == -1)
				return -1;
			break;
		}
		t = ms->offset + sizeof(double);
  		break;

	case FILE_SEARCH:
	case FILE_REGEX: {
		char *cp, *scp;
		int rval;

		cp = strndup(RCAST(const char *, ms->search.s),
		    ms->search.rm_len);
		if (cp == NULL) {
			file_oomem(ms, ms->search.rm_len);
			return -1;
		}
		scp = (m->str_flags & STRING_TRIM) ? file_strtrim(cp) : cp;
					
		rval = file_printf(ms, F(ms, desc, "%s"),
		    file_printable(sbuf, sizeof(sbuf), scp, ms->search.rm_len));
		free(cp);

		if (rval == -1)
			return -1;

		if ((m->str_flags & REGEX_OFFSET_START))
			t = ms->search.offset;
		else
			t = ms->search.offset + ms->search.rm_len;
		break;
	}

	case FILE_DEFAULT:
	case FILE_CLEAR:
	  	if (file_printf(ms, "%s", m->desc) == -1)
			return -1;
		t = ms->offset;
		break;

	case FILE_INDIRECT:
	case FILE_USE:
	case FILE_NAME:
		t = ms->offset;
		break;
	case FILE_DER:
		if (file_printf(ms, F(ms, desc, "%s"),
		    file_printable(sbuf, sizeof(sbuf), ms->ms_value.s,
			sizeof(ms->ms_value.s))) == -1)
			return -1;
		t = ms->offset;
		break;
	case FILE_GUID:
		(void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid);
		if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
			return -1;
		t = ms->offset;
		break;
	default:
		file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
		return -1;
	}
	return CAST(int32_t, t);
}