[comp.lang.c] How to predict size of outcome of vsprintf?

sean@etnibsd.UUCP (Sean McElroy) (03/18/89)

O.K. Unix/C gurus, since vsprintf requires the user to ensure that there
is enough space in the output string, how does one predict the size of
the output string?  Is there a routine which returns the predicted
length of the output string (effectively preforming the printf conversions)
without actually producing the output string?

First an abridged description of what vsprintf does.  Here's it's
declaration:

	char *vsprintf (s, format, ap)
	char *s, *format;
	va_list ap;

Allow me some hand-waving here and let va_list mean "pointer to an argument
list" (see varargs(3) for more detail).  The first argument, "s", is a pointer
to a suitably sized piece of memory.  It is supposed to be large enough
to hold the result of converting the arguments listed in "ap" by the
specifications listed in "format".  Thus the second argument, "format",
is the format string optionally containing conversion specifications.
Finally, "ap" is a pointer to a list of data items which will supply the
data to be converted and then substituted into the string "s".  The function
returns a pointer to "s".

Here's a more general view of the problem.  You are given a format string
of unknown contents (assume that it is a legitamate format string), and
a list of arguments of unknown type (assume that they correspond appropriately
with the conversion specifications in the format string).  How do you
allocate storage for the output string, "s"?

One suggestion is to reproduce the functionality of vsprintf up to the
point where it outputs a character and replace the output-a-character
functionality with count-the-number-of-characters functionality.

I quess since I don't possess the source to vsprintf, et al, I can't be as
certain of reproducing its functionality.  Also this strikes me as such
a fundamental obstacle that it must already have been conquered by someone.

Any suggestions welcome.
-- 
  ____,.,_..,__.,_.,__     Sean Philip McElroy
   __'..__._,_.__.__.__    Eaton Corp., SED
   _,___`_.'__.__.__.__    108 Cherry Hill Dr., Beverly, MA 01922
  ___`..'_,___.__.__,_     uunet!etnibsd!sean

sean@etnibsd.UUCP (Sean McElroy) (03/18/89)

It turns out that vfprintf returns the number of characters transmitted
to the file.  If you use /dev/null as the file then it effectively
returns the size of the output message string for vsprintf (less the
terminator.) 

This solution has satisfied me for now although it's inefficient (and uses
up a file descriptor).  Perhaps there are others that I'm not aware of which
don't have the same inefficiencies.  I'm still interested in hearing about
them.

-- 
  ____,.,_..,__.,_.,__     Sean Philip McElroy
   __'..__._,_.__.__.__    Eaton Corp., SED
   _,___`_.'__.__.__.__    108 Cherry Hill Dr., Beverly, MA 01922
  ___`..'_,___.__.__,_     uunet!etnibsd!sean

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/19/89)

In article <993@etnibsd.UUCP> sean@etnibsd.UUCP (Sean McElroy) writes:
>O.K. Unix/C gurus, since vsprintf requires the user to ensure that there
>is enough space in the output string, how does one predict the size of
>the output string?  Is there a routine which returns the predicted
>length of the output string (effectively preforming the printf conversions)
>without actually producing the output string?

No.  Sometimes you can accurately predict an upper bound on the output
string length; for example if the format is "%d" and the numerical
argument is known to lie between 0 and 5000, the maximum number of
characters for the *sprintf() output will be 5 (including the null
byte at the end).

>Any suggestions welcome.

Don't use *sprintf() when you can't be sure that the output length
will be small enough.  Seriously.

bzs@bu-cs.BU.EDU (Barry Shein) (03/19/89)

It seems like the obvious solution would have been to treat a NULL
string or file pointer as meaning "just return the number of
characters in the result". Oh well.

	-Barry Shein

bzs@bu-cs.BU.EDU (Barry Shein) (03/19/89)

From: gwyn@smoke.BRL.MIL (Doug Gwyn )
>No.  Sometimes you can accurately predict an upper bound on the output
>string length; for example if the format is "%d" and the numerical
>argument is known to lie between 0 and 5000, the maximum number of
>characters for the *sprintf() output will be 5 (including the null
>byte at the end).

Another way to say that is:

	print_width = LOGx(N) + 1

where x (the log base) is the base to be printed in, 10 for %d, 16 for
%x, 8 for %o etc. And add one for sign (+-) if needed.

But of course that doesn't help a lot except with the simplest
cases (eg. try "%-5.*g").

	-Barry Shein

mike@thor.acc.stolaf.edu (Mike Haertel) (03/20/89)

In article <9872@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>No.  Sometimes you can accurately predict an upper bound on the output
>string length; for example if the format is "%d" and the numerical
>argument is known to lie between 0 and 5000, the maximum number of
>characters for the *sprintf() output will be 5 (including the null
>byte at the end).
>
...
>
>Don't use *sprintf() when you can't be sure that the output length
>will be small enough.  Seriously.

The (unreleased) GNU C library contains routines something like:

	int snprintf(char *str, size_t len, const char *fmt, ...);
	int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);

that do bounds checking on their output.  Richard Stallman suggested to
ANSI that they include such routines in the C standard; I am of the
impression that various other people independently made the same or a
similar suggestion.  I also recall a posting by Chris Torek a few
months ago that included an excerpt from a <stdio.h> that included
a routine that looked something like:

	FILE *fmemopen(void *mem, size_t len, const char *how);

This solves the same problem, and offers additional advantages as well.

I do not understand why the pANS does not address this problem in some way.
-- 
Mike Haertel <mike@stolaf.edu>
In Hell they run VMS.

henry@utzoo.uucp (Henry Spencer) (03/20/89)

In article <1618@thor.acc.stolaf.edu> mike@stolaf.edu writes:
>	int snprintf(char *str, size_t len, const char *fmt, ...);
>	int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);
>
>that do bounds checking on their output.  Richard Stallman suggested to
>ANSI that they include such routines in the C standard; I am of the
>impression that various other people independently made the same or a
>similar suggestion...

This is correct.

>I do not understand why the pANS does not address this problem in some way.

Two reasons:

1. Lack of prior experience with it.  Believe it or not, standards
	committees are supposed to be consolidating existing, proven
	practices, not endorsing new and untested ideas.  X3J11, while
	not perfect, has done much better in this area than a lot of
	other language committees.  This is a feature, not a bug!

2. The fact that most of the proposals came very late in the standardization
	process, when quite strong majorities were required to add new stuff.
	I have been told that at least one attempt to add snprintf and
	friends failed by one or two votes.
-- 
Welcome to Mars!  Your         |     Henry Spencer at U of Toronto Zoology
passport and visa, comrade?    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

sean@etnibsd.UUCP (Sean McElroy) (03/21/89)

In article <9872@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>No.  Sometimes you can accurately predict an upper bound on the output
>string length; for example if the format is "%d" and the numerical
>argument is known to lie between 0 and 5000, the maximum number of
>characters for the *sprintf() output will be 5 (including the null
>byte at the end).

If the format specification contains field width specifiers,
this will not work (e.g. sprintf ("%10d", 5000); uses 10 chars + 1
for terminator).  This implies that the format specifications need 
to be parsed in a manner similar to *sprintf in order to accurately
predict the number of chars in the result.  I was looking for something
which did nor require me to re-write *sprintf.  Also recall that
the original problem stated that the types of the input arguments
were unknown.  This implies that the type must be gleaned from
the format specification itself.  Although I'm no expert, I presume
that this is the mechanism *sprintf uses as well (e.g. %d means take
whatever the next input argument is and treat it as an int).

-- 
  ____,.,_..,__.,_.,__     Sean Philip McElroy
   __'..__._,_.__.__.__    Eaton Corp., SED
   _,___`_.'__.__.__.__    108 Cherry Hill Dr., Beverly, MA 01922
  ___`..'_,___.__.__,_     uunet!etnibsd!sean

paul@athertn.Atherton.COM (Paul Sander) (03/21/89)

I seem to have missed the original posting, so I'll follow up Doug Gwyn's
followup...

In article <9872@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <993@etnibsd.UUCP> sean@etnibsd.UUCP (Sean McElroy) writes:
> >O.K. Unix/C gurus, since vsprintf requires the user to ensure that there
> >is enough space in the output string, how does one predict the size of
> >the output string?  Is there a routine which returns the predicted
> >length of the output string (effectively preforming the printf conversions)
> >without actually producing the output string?
> 
> No.  Sometimes you can accurately predict an upper bound on the output
> string length; for example if the format is "%d" and the numerical
> argument is known to lie between 0 and 5000, the maximum number of
> characters for the *sprintf() output will be 5 (including the null
> byte at the end).
> 
> >Any suggestions welcome.
> 
> Don't use *sprintf() when you can't be sure that the output length
> will be small enough.  Seriously.

My guess is that Sean wants to malloc enough space for his output, since
he doesn't know how long it is.  I like to do that from time to time myself
when I have to copy user data (which I have very little control over) into
an array of strings that I display later (e.g., in a scrollpane).

So far, I've been lucky in that my data are usually displayed in some
fixed format, followed by a variable length string.  Calculating the length
of *sprintf is easy in this case (at least in a platform- and application-
dependent way) by summing the ceilings of the lengths of the fixed part of 
the output, and adding the strlen of the variable length part (plus 1 for
the null).

It seems to me that it should be possible to write a printf-like function 
that scans the format string and remaining arguments, returning the
ceiling of the length of the result of the *sprintf.

I realize that this problem can only be solved on a platform-by-platform
basis, but thisseems like a fundamental enough problem that someone somewhere 
must have done it for some platforms.  Has anyone tried?
-- 
Paul Sander        (408) 734-9822       | Do YOU get nervous when a
paul@Atherton.COM                       | sys{op,adm,prg,engr} says
{decwrl,sun,hplabs!hpda}!athertn!paul   | "oops..." ?

scs@adam.pika.mit.edu (Steve Summit) (03/21/89)

In article <28831@bu-cs.BU.EDU> bzs@bu-cs.BU.EDU (Barry Shein) writes:
>Another way to say that is:
>	print_width = LOGx(N) + 1
>where x (the log base) is the base to be printed in...

An occasionally-useful observation is that an upper bound on this
value is something like 8*sizeof(int), which is the number of
characters it could take to print an int in base 2 (some printf's
even provide %b for this purpose!).  As Barry noted, this helps
only in the simplest cases.  (I use it internally to my own
version of printf, for the buffer size in which integer conversion,
before padding, is performed.  Unfortunately, the assumption that
sizeof deals in 8-bit units is not perfectly valid.)


In article <1618@thor.acc.stolaf.edu> mike@stolaf.edu writes:
>The (unreleased) GNU C library contains routines something like:
>	int snprintf(char *str, size_t len, const char *fmt, ...);
>	int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);
>that do bounds checking on their output.
>I also recall a posting by Chris Torek a few
>months ago that included an excerpt from a <stdio.h> that included
>a routine that looked something like:
>	FILE *fmemopen(void *mem, size_t len, const char *how);
>This solves the same problem, and offers additional advantages as well.

My own soon-to-be-released stdio replacement contains

	char *smprintf(char *fmt, ...)

which returns a malloc'ed pointer to an area of memory just big
enough for the formatted string.  (snprintf only allows you to
prevent overflow of a finite-sized buffer; smprintf lets the
resultant buffer be arbitrarily big.)  I may also add

	FILE *strmopen();
	char *strmclose(FILE *);

which would give you a fd on which you could do arbitrary stdio
output, dynamically allocating (and reallocating as needed) an
in-memory buffer, the eventual pointer to which would be returned
by strmclose.  (I've got to think of better names for these; the
'm' is supposed to stand for "malloc" but the overall effect ends
up sounding like "stream" which is misleading.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu

scs@adam.pika.mit.edu (Steve Summit) (03/21/89)

[Apologies if you see this twice; is there a known problem with
canceling cross-posted articles under nntp?]

In article <28831@bu-cs.BU.EDU> bzs@bu-cs.BU.EDU (Barry Shein) writes:
>Another way to say that is:
>	print_width = LOGx(N) + 1
>where x (the log base) is the base to be printed in...

An occasionally-useful observation is that an upper bound on this
value is something like 8*sizeof(int), which is the number of
characters it could take to print an int in base 2 (some printf's
even provide %b for this purpose!).  As Barry noted, this helps
only in the simplest cases.  (I use it internally to my own
version of printf, for the buffer size in which integer conversion,
before padding, is performed.  Unfortunately, the assumption that
sizeof deals in 8-bit units is not perfectly valid.)


In article <1618@thor.acc.stolaf.edu> mike@stolaf.edu writes:
>The (unreleased) GNU C library contains routines something like:
>	int snprintf(char *str, size_t len, const char *fmt, ...);
>	int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);
>that do bounds checking on their output.
>I also recall a posting by Chris Torek a few
>months ago that [mentioned] a routine that looked something like:
>	FILE *fmemopen(void *mem, size_t len, const char *how);
>This solves the same problem, and offers additional advantages as well.

My own soon-to-be-released stdio replacement contains

	char *smprintf(char *fmt, ...)

which returns a malloc'ed pointer to an area of memory just big
enough for the formatted string.  (snprintf only allows you to
prevent overflow of a finite-sized buffer; smprintf lets the
resultant buffer be as big as it needs to be.)  I may also add

	FILE *strmopen();
	char *strmclose(FILE *);

which would give you a fd on which you could do arbitrary stdio
output, dynamically allocating (and reallocating as needed) an
in-memory buffer, the eventual pointer to which would be returned
by strmclose.  (I've got to think of better names for these; the
'm' is supposed to stand for "malloc" but the overall effect ends
up sounding like "stream" which is misleading.)

[Exercise for the student: implement smprintf in terms of
strmopen, vfprintf, and strmclose.]

                                            Steve Summit
                                            scs@adam.pika.mit.edu

henry@utzoo.uucp (Henry Spencer) (03/22/89)

In article <9979@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>My own soon-to-be-released stdio replacement contains
>
>	char *smprintf(char *fmt, ...)

I would urge changing the name, perhaps to msprintf, to avoid a name that
looks very similar to snprintf at first glance.
-- 
Welcome to Mars!  Your         |     Henry Spencer at U of Toronto Zoology
passport and visa, comrade?    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

bzs@bu-cs.BU.EDU (Barry Shein) (03/22/89)

Ok, there are two thoughts here:

	1. How to find out the number of characters a printf
	operation will generate.

	2. How to limit a printf operation to a buffer size.

I suggested the first might be the result of printing to a null
pointer (buffer or file.)

The second could be solved completely transparently by adding a format
effector which indicated the maximum buffer size ("must come first!")
Such as using %n# as in:

	sprintf(buf,"%80#%s",string);		/* 80 char buf including \0 */

or

	sprintf(buf,"%*#%s",BUFSIZ,string);	/* BUFSIZ char buf */

Not sure what "%n.m#" or "%#" might indicate (perhaps the latter would
just return a count of characters, ie, a zero length buffer?)

	-Barry Shein, Software Tool & Die

bader+@andrew.cmu.edu (Miles Bader) (03/22/89)

bzs@bu-cs.BU.EDU (Barry Shein) writes:
> Ok, there are two thoughts here:
> 
>         1. How to find out the number of characters a printf
>         operation will generate.
> 
>         2. How to limit a printf operation to a buffer size.
> 
> I suggested the first might be the result of printing to a null
> pointer (buffer or file.)

What I'd really like would be a new function that could act as a basis
for all the other printf functions, and make it possible to emulate
them in nice ways.

I would make it a varargs function that takes a bounded output buffer
and is restartable at the point where it stops due to running into the
end of the buffer.

E.g. (pardon the name, but I can't think of a better one):

    /* fmtP and valP are modified so that re-calling the function
     * will start formatting where it left off
     */
    int rvsnprintf(buf,maxlen,fmtP,valP)
    char *buf;
    int maxlen;
    char **fmtP;	/* in/out */
    va_list *valP;	/* in/out */

vsprintf, vfprintf, etc, are all trivially derivable from this (as is
the one someone mentioned a while ago that returned a realloced
buffer).

Say I write my own buffered io package; I can just call rvsnprintf like:

    streamvprintf(stream,fmt,val)
    STREAM *stream;
    char *fmt;
    va_list val;
    {
	...
	while(*fmt!='\0){
	    int written=rvsnprintf(stream->pos,stream->left,&fmt,&val);
	    if(*fmt!='\0')  /* ran out of space */
		streamflush(stream);
	    else{
		stream->pos+=written;
		stream->left-=written;
	    }
	}
	...
    }

None of the other proposals I've seen give you this capability (or do
it expensively, like mallocing the buffer), and I can't see how it
would be much more difficult to implement than existing printfs...

-Miles

bader+@andrew.cmu.edu (Miles Bader) (03/22/89)

[Why do problems with my messages always become evident 10 seconds
 AFTER I send them?]

Miles Bader <bader+@andrew.cmu.edu> writes:
>     /* fmtP and valP are modified so that re-calling the function
>      * will start formatting where it left off
>      */
>     int rvsnprintf(buf,maxlen,fmtP,valP)
>     char *buf;
>     int maxlen;
>     char **fmtP;        /* in/out */
>     va_list *valP;      /* in/out */

Oops, you need one more variable, since sometimes a directive (%s,
etc) can be too large for the buffer, so now:

    /* fmtP, valP and offsP are modified so that re-calling the function
     * will start formatting where it left off
     */
    int rvsnprintf(buf,maxlen,fmtP,valP,offsP)
    char *buf;
    int maxlen;
    char **fmtP;        /* in/out */
    va_list *valP;      /* in/out */
    int *offsP;		/* in/out */

*offsP says how many characters to drop before putting stuff into the
buffer, and should initially be 0.  With this change, it should work
correctly for any size output buffer (even small ones).

>     {
>         ...
>         while(*fmt!='\0){
>             int written=rvsnprintf(stream->pos,stream->left,&fmt,&val);

Becomes:

    {
	int offs=0;
        ...
        while(*fmt!='\0){
            int written=rvsnprintf(stream->pos,stream->left,&fmt,&val,&offs);

-Miles

chris@mimsy.UUCP (Chris Torek) (03/22/89)

In article <28874@bu-cs.BU.EDU> bzs@bu-cs.BU.EDU (Barry Shein) writes:
>The [limiting problem] could be solved completely transparently by adding
>a format effector which indicated the maximum buffer size ("must come
>first!") Such as using %n# as in:

`#' is out; it is a flag (meaning `alternate output format' and used
by o, x, and e f and g conversions).  But aesthetically speaking, it
seems to me that this is almost as bad as the `%n' format.  (Well,
maybe half as bad.)  I would prefer snprintf() and/or msprintf().
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chris@mimsy.UUCP (Chris Torek) (03/22/89)

In article <wY9m4Hy00UkaI=3Ihb@andrew.cmu.edu> bader+@andrew.cmu.edu
(Miles Bader) writes:
>What I'd really like would be a new function that could act as a basis
>for all the other printf functions, and make it possible to emulate
>them in nice ways.
>
>I would make it a varargs function that takes a bounded output buffer
>and is restartable at the point where it stops due to running into the
>end of the buffer.

This is fairly difficult to implement (one wants coroutines for something
like this).  Instead, why not allow stdio streams to `read' and `write'
via user-provided functions?  Everyone knows how to use read() and
write(); simply provide your own write() that mallocs space, or prints
in a window, or whatever.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

rbutterworth@watmath.waterloo.edu (Ray Butterworth) (03/22/89)

In article <16491@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <wY9m4Hy00UkaI=3Ihb@andrew.cmu.edu> bader+@andrew.cmu.edu
> (Miles Bader) writes:
> >What I'd really like would be a new function that could act as a basis
> >for all the other printf functions, and make it possible to emulate
> >them in nice ways.
> >
> >I would make it a varargs function that takes a bounded output buffer
> >and is restartable at the point where it stops due to running into the
> >end of the buffer.
> 
> This is fairly difficult to implement (one wants coroutines for something
> like this).  Instead, why not allow stdio streams to `read' and `write'
> via user-provided functions?  Everyone knows how to use read() and
> write(); simply provide your own write() that mallocs space, or prints
> in a window, or whatever.

There is something else that is usually fairly easy to implement though,
even if the code for the implementation is non-portable.

A typical implementation of sprintf simply builds a FILE* and calls
fprintf on it, while a typical implementation of stdio has some
function that is called when an output buffer fills.

One could easily write a function that is similar to sprintf but is
passed a pointer to the buffer size.  When the buffer fills up,
instead of "flushing" it, realloc is called and the fprintf continues.
The function would return the pointer to the possibly reallocated
buffer and would possibly have stuffed a new size through the
buffer size pointer.

In many stdio implementations this can be written with only a few
lines of code, and I'd say it is far more useful than many of the
alternatives that have been suggested.
e.g. a function that returns an estimate of how many characters
would be needed (this doubles the cpu since it effectively calls
printf twice), or a function that limits the output to the buffer
(you have to check if the buffer filled, and if it did you have
to realloc another bigger one and call the function right from
the beginning again).

mike@thor.acc.stolaf.edu (Mike Haertel) (03/23/89)

In article <16491@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>This is fairly difficult to implement (one wants coroutines for something
>like this).  Instead, why not allow stdio streams to `read' and `write'
>via user-provided functions?  Everyone knows how to use read() and
>write(); simply provide your own write() that mallocs space, or prints
>in a window, or whatever.

I have been writing just exactly such a stdio package lately.

The only things I have left to do are printf() and friends, and scanf()
and friends.  The reason I am writing it is I am experimenting with
standalone programs on my machine, and I wanted a stdio library.  It
also works on Unix, that is where I test it.  Incidentally the stuff
that is written so far all conforms to the pANS.  When I finish it
I will make it available to anyone who is interested.

The way it works is like this:

typedef struct _FILE {
    ...
    struct __iofuncs *__iofuncs;	/* Vector to actual I/O functions. */
    void *__info;			/* Opaque info for I/O functions. */
    ...
} FILE;

When fopen() is called it loops through all available I/O function tables,
trying the open() entry in each one (iofuncs->open() just gets the same
arguments as fopen()); the first to return non-NULL has that value
installed in FILE->__info.

Then, for example, the actual write call in fflush() looks like this:

    (*fp->__iofuncs->write)(fp->__info, buf, len);

There will be a library entry point to install user-defined I/O
function tables.

I haven't decided exactly how to do printf() yet; I would like to
have a function switch table based on format letters so I can have
an extensible printf().  I will probably try that tonight.  I will
not be doing the floating point stuff in the near future as the
standalone environment I am using is a 68010, and I have not yet
written the floating point run time support for the compiler, and
I really don't feel like doing that any time soon, I don't use
floating point much . . .

I got the idea for the extensible printf() from the manual page
describing the FIO package and in particular fmtinstall() in
the Ninth Edition manual.  Whoever you are at Bell Labs
who invented that, thanks, it's a cool idea.
-- 
Mike Haertel <mike@stolaf.edu>
In Hell they run VMS.

les@chinet.chi.il.us (Leslie Mikesell) (03/23/89)

In article <28874@bu-cs.BU.EDU> bzs@bu-cs.BU.EDU (Barry Shein) writes:

>Ok, there are two thoughts here:

>	1. How to find out the number of characters a printf
>	operation will generate.
>	2. How to limit a printf operation to a buffer size.

Or a third, which is what I usually want:

 3. Give me a pointer to a buffer with my formatted string in it.
    This is trivial after doing operation (1) but shouldn't it
    be possible to do it in one operation?

Les Mikesell

bader+@andrew.cmu.edu (Miles Bader) (03/23/89)

chris@mimsy.UUCP (Chris Torek) writes:
> In article <wY9m4Hy00UkaI=3Ihb@andrew.cmu.edu> bader+@andrew.cmu.edu
> (Miles Bader) writes:
> >What I'd really like would be a new function that could act as a basis
> >for all the other printf functions, and make it possible to emulate
> >them in nice ways.
> >
> >I would make it a varargs function that takes a bounded output buffer
> >and is restartable at the point where it stops due to running into the
> >end of the buffer.
> 
> This is fairly difficult to implement (one wants coroutines for something
> like this).  Instead, why not allow stdio streams to `read' and `write'
> via user-provided functions?  Everyone knows how to use read() and
> write(); simply provide your own write() that mallocs space, or prints
> in a window, or whatever.

I agree that stdio should have been written with user-provided read/write
routines.  But I disagree that a restartable sprintf would be difficult.  The
code needn't be much different at all from a putc based printf (the only
difference is that state changes inside the routine are passed out of it).

One reason why I like the restartable printf idea is that it's lower overhead
and less complex than creating/destroying a stream just for the purpose of
implementing sprintf.  I just wrote my own stdio-type package; I don't want
to have to go though the overhead of passing things through a stdio stream
just to get put into MY stream (not that it would be that high; but it's the
principle of the thing).

-Miles

karl@haddock.ima.isc.com (Karl Heuer) (03/23/89)

In <1989Mar21.183741.1089@utzoo.uucp> henry@utzoo (Henry Spencer) writes:
>In <9979@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>>My own soon-to-be-released stdio replacement contains
>>	char *smprintf(char *fmt, ...)
>
>I would urge changing the name, perhaps to msprintf, to avoid a name that
>looks very similar to snprintf at first glance.

But `msprintf' has the flaw that the va_list version would be named
`vmsprintf', which suggests that it has something to do with a certain
obscure operating system.  I think I'd go with `mprintf'.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

michael@garfield.MUN.EDU (Mike Rendell) (03/23/89)

In article <wY9m4Hy00UkaI=3Ihb@andrew.cmu.edu> bader+@andrew.cmu.edu
(Miles Bader) writes:
>What I'd really like would be a new function that could act as a basis
>for all the other printf functions, and make it possible to emulate
>them in nice ways.
>
>I would make it a varargs function that takes a bounded output buffer
>and is restartable at the point where it stops due to running into the
>end of the buffer.

I wrote a version of doprnt() which does something like this.  Instead
of taking a FILE * argument it's passed a function pointer and a
"generic argument" (void/char *).  new_doprnt() fills up a stack buffer
and calls the function (which takes the same arguments as fwrite()) to
deal with it.  This makes printf() and a bounds checking sprintf() (or
a re-alloc()ing sprintf()) easy to write as well as providing a simple
method for programmers to hook into it.  I've used it in some screen
based programs to page output and in some stand alone programs to do
output to a console.  The only draw back is that it doesn't handle
%[egf] - but who needs those anyway :-).

Mike Rendell				Department of Computer Science
michael@garfield.mun.edu		Memorial University of Newfoundland
uunet!garfield!michael			St. John's, Nfld., Canada
 (709) 737-4550				A1C 5S7

jbayer@ispi.UUCP (Jonathan Bayer) (03/27/89)

In article <1989Mar21.183741.1089@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <9979@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>>My own soon-to-be-released stdio replacement contains
>>
>>	char *smprintf(char *fmt, ...)
>
>I would urge changing the name, perhaps to msprintf, to avoid a name that
					    ^^^^^^^^
So now Microsoft has it's own version of printf :-)




JB
-- 
Jonathan Bayer			      Beware: The light at the end of the
Intelligent Software Products, Inc.	      tunnel may be an oncoming dragon
19 Virginia Ave.				...uunet!ispi!jbayer
Rockville Centre, NY 11570  (516) 766-2867    jbayer@ispi.UUCP

orr@taux01.UUCP (Orr Michael ) (04/03/89)

In article <12135@haddock.ima.isc.com> 
   karl@haddock.ima.isc.com (Karl Heuer) writes:
>
>But `msprintf' has the flaw that the va_list version would be named
>`vmsprintf', which suggests that it has something to do with a certain
>obscure operating system.
>
>Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
 ... In which 'printf' itself is limited to 512 chars at most, getting you
a crash if you try printing longer strings ...


-- 
orr@nsc			  	      IBM's motto: Machines should work,
{amdahl,decwrl,hplabs,pyramid,sun}!nsc!orr         People should think.
                                 	      Orr's remark: Neither do.
Disclaimer: Opinions, come home. All is forgiven. Papa.