develooper Front page | perl.perl5.porters | Postings from June 2007

[PATCH] Re: vsprintf

Thread Previous | Thread Next
Andy Dougherty
June 14, 2007 10:13
[PATCH] Re: vsprintf
Message ID:
On Wed, 13 Jun 2007, Andy Dougherty wrote:

> On Thu, 12 Apr 2007, Nicholas Clark wrote:
> > So we have this to determine the return value of vsprintf:
> [omitted]
> This patch fixes that problem.  There are still some murky corners dealing 
> with what happens if the test program won't compile, but at least the 
> resulting default guess is likely to be right.
> I didn't look at how this is used in util.c yet.  One thing at a time.

This patch looks at how this stuff gets used in util.c.  The most 
important thing is probably the comment saying in effect "If you got a 
problem here, you probably have a *BIG* Configure problem elsewhere.  
Solve that Configure problem and this vsprintf problem will probably go 

> >In turn, that symbol is only used here in util.c:
> >
> >#ifndef HAS_VPRINTF
> >
> >char *
> >#else
> >int
> >#endif
> >vsprintf(char *dest, const char *pat, char *args)
> >{
> >
> >...
> >
> >which is not exactly useful, as USE_CHAR_VSPRINTF is always going to be undef
> >if HAS_VPRINTF is undef.

> >
> >So, what to do?

> >Part of the issue is that really we want a 3 way (or even 4 way) of

> >0: you don't have vsprintf
> >1: you have it, but can't figure out the return type
> >2: you have it, and it's char *
> >3: you have it, and it's int. (the C89 version)
> >
> >and really, these days we're only interested in 3 or !3

> >Nicholas Clark

I suspect that this part of util.c hasn't compiled (under the default
configuration) since 5.8.0.  (The putc() gets defined away by the
PerlIO stuff.)  In nearly every case I have seen where it appears to
be needed (i.e. case 0), it has turned out to be a symptom of a bigger
Configure problem.  Solving that bigger Configure problem has made this
issue go away.

I could imagine some cross-compilation or embedded set-up where a stripped
down C library was missing vprintf and where this function was needed.
(I don't recall ever encountering such a case, but I imagine one could
exist.)  In such a case, I don't know if a vsprintf() prototype would
or wouldn't appear in the system #includes.  (I've seen precedents
both ways.)

I decided to leave in USE_CHAR_VSPRINTF (defaulting to the C89
case of having vsprintf() return an integer).  In the extremely rare
case where someone needs to actually compile this part of util.c, they
may need the ability to override Configure's default.  This gives them
a handy hook to do so.  Of course, they'll probably have to do a lot
more work if their stdio.h isn't very BSD-ish, but I doubt it's worth
expending much effort on that hypothetical case right now.

Anyway, this patch at least has a chance of compiling again, and, more
importantly, contains a useful comment pointing back to the INSTALL

--- perl-current/util.c	Thu May  3 21:01:41 2007
+++ perl-andy/util.c	Thu Jun 14 11:49:37 2007
@@ -1832,24 +1832,52 @@
 #endif /* !HAS_MEMCMP || !HAS_SANE_MEMCMP */
 #ifndef HAS_VPRINTF
+/* This vsprintf replacement should generally never get used, since
+   vsprintf was available in both System V and BSD 2.11.  (There may
+   be some cross-compilation or embedded set-ups where it is needed,
+   however.)
+   If you encounter a problem in this function, it's probably a symptom
+   that Configure failed to detect your system's vprintf() function.
+   See the section on "item vsprintf" in the INSTALL file.
+   This version may compile on systems with BSD-ish <stdio.h>,
+   but probably won't on others.
 char *
-vsprintf(char *dest, const char *pat, char *args)
+vsprintf(char *dest, const char *pat, void *args)
     FILE fakebuf;
+#if defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE)
+    FILE_ptr(&fakebuf) = (STDCHAR *) dest;
+    FILE_cnt(&fakebuf) = 32767;
+    /* These probably won't compile -- If you really need
+       this, you'll have to figure out some other method. */
     fakebuf._ptr = dest;
     fakebuf._cnt = 32767;
 #ifndef _IOSTRG
 #define _IOSTRG 0
     fakebuf._flag = _IOWRT|_IOSTRG;
     _doprnt(pat, args, &fakebuf);	/* what a kludge */
-    (void)putc('\0', &fakebuf);
+#if defined(STDIO_PTR_LVALUE)
+    *(FILE_ptr(&fakebuf)++) = '\0';
+    /* PerlIO has probably #defined away fputc, but we want it here. */
+#  ifdef fputc
+#    undef fputc  /* XXX Should really restore it later */
+#  endif
+    (void)fputc('\0', &fakebuf);

    Andy Dougherty

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About