/*
 * The authors of this software are Rob Pike and Ken Thompson.
 *              Copyright (c) 2002 by Lucent Technologies.
 * Permission to use, copy, modify, and distribute this software for any
 * purpose without fee is hereby granted, provided that this entire notice
 * is included in all copies of any software which is or includes a copy
 * or modification of this software and in all copies of the supporting
 * documentation for such software.
 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 */

#pragma	lib	"libc"

typedef struct Fmt	Fmt;
struct Fmt{
	unsigned char	runes;		/* output buffer is runes or chars? */
	void	*start;			/* of buffer */
	void	*to;			/* current place in the buffer */
	void	*stop;			/* end of the buffer; overwritten if flush fails */
	int	(*flush)(Fmt *);	/* called when to == stop */
	void	*farg;			/* to make flush a closure */
	int	nfmt;			/* num chars formatted so far */
	va_list	args;			/* args passed to dofmt */
	Rune	r;			/* % format Rune */
	int	width;
	int	prec;
	unsigned long	flags;
	char	*decimal;	/* decimal point; cannot be "" */

	/* For %'d */
	char *thousands;	/* separator for thousands */

	/*
	 * Each char is an integer indicating #digits before next separator. Values:
	 *	\xFF: no more grouping (or \x7F; defined to be CHAR_MAX in POSIX)
	 *	\x00: repeat previous indefinitely
	 *	\x**: count that many
	 */
	char	*grouping;		/* descriptor of separator placement */
};

enum{
	FmtWidth	= 1,
	FmtLeft		= FmtWidth << 1,
	FmtPrec		= FmtLeft << 1,
	FmtSharp	= FmtPrec << 1,
	FmtSpace	= FmtSharp << 1,
	FmtSign		= FmtSpace << 1,
	FmtApost		= FmtSign << 1,
	FmtZero		= FmtApost << 1,
	FmtUnsigned	= FmtZero << 1,
	FmtShort	= FmtUnsigned << 1,
	FmtLong		= FmtShort << 1,
	FmtVLong	= FmtLong << 1,
	FmtComma	= FmtVLong << 1,
	FmtByte		= FmtComma << 1,
	FmtLDouble	= FmtByte << 1,

	FmtFlag		= FmtLDouble << 1
};

extern	int	(*fmtdoquote)(int);

int		dofmt(Fmt *, char *);
int		dorfmt(Fmt *, Rune *);
double	fmtcharstod(int(*)(void*), void *);
int		fmtfdflush(Fmt *);
int		fmtfdinit(Fmt *, int, char *, int);
int		fmtinstall(int, int (*)(Fmt*));
int		fmtnullinit(Fmt*);
void	fmtlocaleinit(Fmt*, char*, char*, char*);
int		fmtprint(Fmt *, char *, ...);
int		fmtrune(Fmt *, int);
int		fmtrunestrcpy(Fmt *, Rune *);
int		fmtstrcpy(Fmt *, char *);
char*	fmtstrflush(Fmt *);
int		fmtstrinit(Fmt *);
double	fmtstrtod(const char *, char **);
int		fmtvprint(Fmt *, char *, va_list);
int		fprint(int, char *, ...);
int		print(char *, ...);
void	quotefmtinstall(void);
int		quoterunestrfmt(Fmt *);
int		quotestrfmt(Fmt *);
char*	seprint(char *, char *, char *, ...);
char*	smprint(char *, ...);
int		snprint(char *, int, char *, ...);
int		sprint(char *, char *, ...);
int		vfprint(int, char *, va_list);
char*	vseprint(char *, char *, char *, va_list);
char*	vsmprint(char *, va_list);
int		vsnprint(char *, int, char *, va_list);
/*
 * error string for %r
 * supplied on per os basis, not part of fmt library
 */
int		errfmt(Fmt *f);

#pragma	varargck	argpos	fmtprint	2
#pragma	varargck	argpos	fprint		2
#pragma	varargck	argpos	print		1
#pragma	varargck	argpos	seprint		3
#pragma	varargck	argpos	smprint		1
#pragma	varargck	argpos	snprint		3
#pragma	varargck	argpos	sprint		2

Rune*	runefmtstrflush(Fmt *);
int		runefmtstrinit(Fmt *);
Rune*	runeseprint(Rune *, Rune *, char *, ...);
Rune*	runesmprint(char *, ...);
int		runesnprint(Rune *, int, char *, ...);
int		runesprint(Rune *, char *, ...);
Rune*	runevseprint(Rune *, Rune *, char *, va_list);
Rune*	runevsmprint(char *, va_list);
int		runevsnprint(Rune *, int, char *, va_list);

#pragma	varargck	argpos	runeseprint	3
#pragma	varargck	argpos	runesmprint	1
#pragma	varargck	argpos	runesnprint	3
#pragma	varargck	argpos	runesprint	2

#pragma	varargck	type	"lld"	vlong
#pragma	varargck	type	"llx"	vlong
#pragma	varargck	type	"lld"	uvlong
#pragma	varargck	type	"llx"	uvlong
#pragma	varargck	type	"ld"	long
#pragma	varargck	type	"lx"	long
#pragma	varargck	type	"lb"	long
#pragma	varargck	type	"ld"	ulong
#pragma	varargck	type	"lx"	ulong
#pragma	varargck	type	"lb"	ulong
#pragma	varargck	type	"d"	int
#pragma	varargck	type	"x"	int
#pragma	varargck	type	"c"	int
#pragma	varargck	type	"C"	int
#pragma	varargck	type	"b"	int
#pragma	varargck	type	"d"	uint
#pragma	varargck	type	"x"	uint
#pragma	varargck	type	"c"	uint
#pragma	varargck	type	"C"	uint
#pragma	varargck	type	"b"	uint
#pragma	varargck	type	"d"	int32
#pragma	varargck	type	"x"	int32
#pragma	varargck	type	"c"	int32
#pragma	varargck	type	"C"	int32
#pragma	varargck	type	"b"	int32
#pragma	varargck	type	"d"	uint32
#pragma	varargck	type	"x"	uint32
#pragma	varargck	type	"c"	uint32
#pragma	varargck	type	"C"	uint32
#pragma	varargck	type	"b"	uint32
#pragma	varargck	type	"f"	double
#pragma	varargck	type	"e"	double
#pragma	varargck	type	"g"	double
#pragma	varargck	type	"s"	char*
#pragma	varargck	type	"q"	char*
#pragma	varargck	type	"S"	Rune*
#pragma	varargck	type	"Q"	Rune*
#pragma	varargck	type	"r"	void
#pragma	varargck	type	"%"	void
#pragma	varargck	type	"n"	int*
#pragma	varargck	type	"p"	uintptr
#pragma	varargck	type	"p"	void*
#pragma	varargck	flag	','
#pragma	varargck	flag	' '
#pragma	varargck	flag	'h'
#pragma varargck	type	"<"	void*
#pragma varargck	type	"["	void*
#pragma varargck	type	"H"	void*
#pragma varargck	type	"lH"	void*
