shithub: mc

ref: c62a377b27f8259a9270d95d02e8acbca21c2ac9
dir: /fmt.myr/

View raw version
use "die.use"
use "sys.use"
use "types.use"
use "utf.use"

pkg std =
	const bfmt	: (buf : byte[,], fmt : byte[,], args:... -> size)
	const put	: (fmt : byte[,], args:... -> size)
;;

const put = {fmt, args
	var buf : byte[2048]
	var n
	
	n = bfmt(buf[0,2048], fmt, args)
	write(1, buf[0,n])
	-> n
}

const bfmt = {buf, fmt, args
	var c
	var n
	var ap
	var i_val;
	var s_val;

	n = 0
	ap = &args castto(byte*)
	while fmt.len
		(c, fmt) = striter(fmt)
		if c == '%'
			(c, fmt) = striter(fmt)
			match c
			's':
				ap = align(ap, sizeof(void*))
				s_val = *(ap castto(byte[,]*))
				n += strfmt(buf[n, buf.len], s_val)
				ap = add(ap, sizeof(byte[,]))
				;;
			/* format integers */
			'b':
				ap = align(ap, sizeof(int8));
				i_val = *(ap castto(int8*)) castto(int64)
				n += intfmt(buf[n, buf.len], i_val, 10)
				ap = add(ap, sizeof(int8))
				;;
			/*
			'w':
				ap = align(ap, sizeof(int16));
				i_val = *(ap castto(int16*)) castto(int64)
				n += intfmt(buf[n, buf.len], i_val, 10)
				ap = add(ap, sizeof(int16))
				;;
			*/
			'i':
				ap = align(ap, sizeof(int32));
				i_val = *(ap castto(int32*)) castto(int64)
				n += intfmt(buf[n, buf.len], i_val, 10)
				ap = add(ap, sizeof(int32))
				;;
			'l':
				ap = align(ap, sizeof(int64));
				i_val = *(ap castto(int64*))
				n += intfmt(buf[n, buf.len], i_val, 10)
				ap = add(ap, sizeof(int64))
				;;
			'p':
				ap = align(ap, sizeof(byte*));
				i_val = *(ap castto(int64*))
				strfmt(buf[n,buf.len], "0x")
				n += intfmt(buf[n, buf.len], i_val, 16)
				ap = add(ap, sizeof(byte*))
				;;
			;;
		else
			n += encode(buf[n,buf.len], c)
		;;
	;;
	-> n
}

const strfmt = {buf, str
	var i
	
	for i = 0; i < min(str.len, buf.len); i++
		buf[i] = str[i]
	;;
	-> i
}

const intfmt = {buf, val, base
	var digits = [
		'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
	]
	var b : char[32]
	var i
	var j
	var n

	n = 0
	i = 0
	if val < 0
		b[i] = '-'
		i++
	;;
	while val != 0
		b[i] = digits[val % base]
		val /= base
		i++
	;;
	n = 0
	for j = i-1; j >= 0; j--
		n += encode(buf[n,buf.len], b[j])
	;;
	-> n 
}

const min = {a : size, b : size
	if a < b
		-> a
	else
		-> b
	;;
}

const align = {p, align
	var v
	
	v = p castto(intptr)
	v = (v + align - 1) & ~(align - 1)
	-> v castto(byte*)
}

const add = {p, sz
	-> ((p castto(intptr)) + sz) castto(byte*)
}