Subject: Re: strformat() ?
To: None <tech-kern@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-kern
Date: 09/09/1999 16:59:25
> Before adding other formats to the corename stuff I wonder if it's
> worth implemeting a generic function for this.  Something like:

> strformat(char *dst, size_t dstlen, const char *template, const char *format,
>     ...);

> A sample call would be here:
> strformat(name, MAXPATHLEN, curproc->p_limit->pl_corename, "nup",
>     "%s", curproc->p_comm,
>     "%s", curproc->p_pgrp->pg_session->s_login,    
>     "%d", curproc->p_pid);

> That is, for each format we provide the snprintf format to convert
> the value, and the value.

This is a nice idea, but I don't think it can ever fly in this form.
Part of the reason was already addressed by someone else - it's hard to
do unless you make grossly nonportable assumptions about how the
argument list is passed - and another part of the reason is that it
requires computing all the values, even if some of them prove to be
unnecessary.  When the values are as simple as curproc->p_comm, this is
not a big deal, but if any of them are expensive to compute, it could
be important to compute them only when needed.  (It also assumes that
any given format always produces the same string in any given call,
which is not necessarily true, and it assumes that this string can be
generated by a simple printf format, which also may be false.)

How about

static void corename_format_n(
	void *arg,
	/* other args to be determined */
	)
{
	some_callback(...,((struct proc *)arg)->p_comm);
}

static void corename_format_p(
	void *arg,
	/* other args to be determined */
	)
{
	some_other_callback(...,"%d",((struct proc *)arg)->p_pid);
}

....
strformat(name,MAXPATHLEN,curproc->p_limit->pl_corename,
	'n', corename_format_n, (void *)curproc,
	'u', corename_format_u, (void *)curproc,
	'p', corename_format_p, (void *)curproc,
	0 );

If you're willing to write in gcc rather than C (are we, for the
kernel?), you can even do away with the void * argument, a la

strformat(name,MAXPATHLEN,curproc->p_limit->pl_corename,
	'n', ({ static void lambda(...)
		{ some_callback(...,curproc->p_comm); }
		&lambda; }),
	'u', ...,
	'p', ({ static void lambda(...)
		{ some_other_callback(...,"%d",curproc->p_p_pid); }
		&lambda; }),
	0 );

which has the advantage of keeping the code next to the use.

While I'm on the subject, two more possible formats:

1) a timestamp (probably would have to be a time_t, in decimal or hex)

2) a unique string (the idea of which is to ensure that it's possible
    to set a format such that no two processes using it will ever dump
    core to the same name)

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B