Re: [Freeciv-Dev] patch: provide snprintf
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Oops, sorry for empty message, lets try that again...
David Pfitzner wrote:
> frankly if we're going to include
> a more portable alternative, I'd prefer to include _just_ the
> more portable version, and accept any performance penalties (or
> whatever) on platforms where mprotect would have worked.
Actually, if we were to ignore performance issues, one option
would be the "write to a file" trick. The following patch does
this; I think it works, and it should be pretty portable.
Just don't using snprintf inside tight loops :-)
Any system for which this doesn't work (eg, broken tmpfile()?)
we can probably laugh at for not providing ANSI/ISO Standard C.
Though in the past, after composing ourselves we have tried
somewhat to support such systems anyway...
I think this works ok regardless of funny \n\r treatment etc;
it doesn't do the traditional "write to /dev/null to work out
the size" thing, so we don't depend on /dev/null existing, and
plus it just works better this way.
I'm not sure if I'm seriously suggesting this... Any takers? :-)
Remember this would only be for systems without a native vsnprintf.
-- David
ps: errata: ok, some of my int vars should be size_t, and it
should check the return value of vfprintf for error.
/* by dwp */
#include <stdio.h>
#include <stdarg.h>
/* vsnprintf using tmpfile().
*
* We never close or remove the file; if tmpfile() works,
* that should happen automatically when the program terminates
* (assuming normal termination).
*
*/
int my_vsnprintf(char *str, size_t nspec, const char *format, va_list ap)
{
static FILE *fp = NULL;
int nwrite, nread, n;
if (fp == NULL) {
fp = tmpfile();
if (fp == NULL) {
fprintf(stderr, "vsnprintf: tmpfile failed");
exit(1);
}
}
nwrite = vfprintf(fp, format, ap);
n = (nwrite < nspec ? nwrite : nspec);
rewind(fp);
nread = fread(str, 1, n, fp);
if (nread != n) {
fprintf(stderr, "vsnprintf: short fread n=%ld nread=%ld",
(long)n, (long)nread);
}
if (nread < nspec) {
str[nread] = '\0';
}
rewind(fp); /* for next time */
return nread;
}
int my_snprintf(char *str, size_t n, const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = my_vsnprintf(str, n, format, ap);
va_end(ap);
return ret;
}
#ifdef TEST
int main(void)
{
char s[] = "012345678";
static char buf[50];
my_snprintf(s, 3, "%s", "abcdefg");
puts(s);
my_snprintf(buf, 3, "%s", "abcdefg");
puts(buf);
my_snprintf(buf, 49, "%s", "abcdefg");
puts(buf);
return 0;
}
#endif
|
|