Mirrored from: http://www.quanstro.net/plan9/pctv.html

A small illustration of how to use typeof in ken's c compiler to implement %v.

A small change to the compiler's varadic function checking is required to allow a single verb to use more than one argument. For brevity this change is excluded.

#include <u.h>
#include <libc.h>

int
fmtv(Fmt *f)
{
	ulong sign;
	extern int _ifmt(Fmt*);
	extern int _strfmt(Fmt*);
	extern int _runesfmt(Fmt*);

	sign = va_arg(f->args, ulong);
	switch(sign){
	case signof(uchar):
		f->flags |= FmtUnsigned;
	case signof(char):
		f->flags |= FmtByte;
		f->r = f->flags&FmtSharp? 'x': 'd';
		return _ifmt(f);
	case signof(ushort):
		f->flags |= FmtUnsigned;
	case signof(short):
		f->flags |= FmtShort;
		f->r = f->flags&FmtSharp? 'x': 'd';
		return _ifmt(f);
	case signof(uint):
		f->flags |= FmtUnsigned;
	case signof(int):
		f->r = f->flags&FmtSharp? 'x': 'd';
		return _ifmt(f);
	case signof(ulong):
		f->flags |= FmtUnsigned;
	case signof(long):
		f->r = f->flags&FmtSharp? 'x': 'd';
		f->flags |= FmtLong;
		return _ifmt(f);
	case signof(vlong):
		f->flags |= FmtUnsigned;
	case signof(uvlong):
		f->r = f->flags&FmtSharp? 'x': 'd';
		f->flags |= FmtVLong;
		return _ifmt(f);

	case signof(char*):
	case signof(char[]):
		return _strfmt(f);
	case signof(Rune*):
	case signof(Rune[]):
		return _runesfmt(f);

	default:
		return fmtprint(f, "<%%v>");
	}
}

#pragma	varargck	type	"v"	ulong,char
#pragma	varargck	type	"v"	ulong,short
#pragma	varargck	type	"v"	ulong,int
#pragma	varargck	type	"v"	ulong,long
#pragma	varargck	type	"v"	ulong,vlong
#pragma	varargck	type	"v"	ulong,uchar
#pragma	varargck	type	"v"	ulong,ushort
#pragma	varargck	type	"v"	ulong,uint
#pragma	varargck	type	"v"	ulong,ulong
#pragma	varargck	type	"v"	ulong,uvlong

#pragma	varargck	type	"v"	ulong,char*

#define	V(x)	signof(x), (x)
void
main(void)
{
	u32int x;

	fmtinstall('v', fmtv);

	print("%v\n", V(1));
	print("%v\n", V("abc"));

	x = 32;
	print("%v\n", V(x));
	print("%#v\n", V(x));

	print("%v\n", V((char)x));
	print("%v\n", V((int)x));
	print("%v\n", V((long)x));
	print("%v\n", V((vlong)x));

	exits("");
}