We are developing some software a Texas DSP, where they provide a
compiler(Code Composer Studio), there are so many bugs with this compiler,
the one I am having trouble with is sprintf, it does not function properly.
I would be grateful for any information on source code for this function.
Thanks.
Regards
Ibrahim KHAN
--
comp.lang.c.moderated - moderation address: cl...@plethora.net
> Hi,
>
> We are developing some software a Texas DSP, where they provide a
> compiler(Code Composer Studio), there are so many bugs with this compiler,
> the one I am having trouble with is sprintf, it does not function properly.
>
> I would be grateful for any information on source code for this function.
>
> Thanks.
>
> Regards
> Ibrahim KHAN
#1. The book:
The Standard C Library
P. J. Plauger
Prentice Hall 1992
Softcover ISBN 0131315099
But notice that this does not give you the right to just use the code.
#2. The source code for the Gnu compiler is available.
Jack Klein
--
Home: http://jackklein.home.att.net
Whilst I am ready to believe that the library may be in error, please
bear in mind that most instances of "a bug in the compiler" (or, indeed,
the library) usually turn out to be bugs in the user code.
>
> I would be grateful for any information on source code for this function.
--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html
>Ibrahim Khan wrote:
>> We are developing some software a Texas DSP, where they provide a
>> compiler(Code Composer Studio), there are so many bugs with this compiler,
>> the one I am having trouble with is sprintf, it does not function properly.
>Whilst I am ready to believe that the library may be in error, please
>bear in mind that most instances of "a bug in the compiler" (or, indeed,
>the library) usually turn out to be bugs in the user code.
Particularly with sprintf, one of the hardest functions to use
properly.
Did you #include <stdio.h>? That is essential to the black magic
necessary for variable argument lists in sprintf.
>> I would be grateful for any information on source code for this
>>function.
Not only is sprintf hard to use correctly, it's very, very difficult
to write correctly. Leaving aside the variable argument list black
magic, it can't be done without access to and understanding of the
implementation's treatment of FILE structs and interface with the file
system. If i/o relies on compiler black magic (which is very likely),
you can forget it; if it doesn't, at a minimum you still have to
re-write the entire stdio library to be able to mix calls to your
sprintf with calls to other stdio functions.
Leaving all that aside, stdio cannot be written in C unless the
implementation provides a C interface to the low-level routines for
actually talking to the file system.
... as examination of those sources will demonstrate.
If it really is a bug in sprintf, you've realistically got two
options: get a different compiler, or try to rewrite the sprintf calls
to build up the strings character-by-character.
--
dhs spe...@panix.com
Others have already pointed you at the gnu implementation the C library.
However, the chances of that working with *your* compiler are pretty
low.
Assuming your usage of sprintf is valid, I recommend a bug report to
the vendor. If you post a "small but complete" example of how you
use sprintf to this group, I'm sure some people here will happily
check to see if your usage is valid.
What do FILE structs and i/o have to do with sprintf? sprintf() writes
to a string (a memory buffer supplied by the calling function).
--
Rex Barzee
Hewlett-Packard Manageability Solutions Lab
[ ... ]
> Not only is sprintf hard to use correctly, it's very, very difficult
> to write correctly. Leaving aside the variable argument list black
> magic,
The variable argument list black magic is encapsulated entirely
inside of the variable-argument macros in stdarg.h -- IOW, neither
sprintf nor any of its close relatives should deal directly in any
black magic at all.
> it can't be done without access to and understanding of the
> implementation's treatment of FILE structs and interface with the file
> system.
What would sprintf have to do with FILE structs or file systems?
sprintf doesn't deal with files at all -- it produces output in a
string, not a file.
Even when writing printf (for one example) there's no need for
knowledge of anything internal to the FILE *, or anything similar.
Assuming you have a working version of vsprintf, you can produce an
implementation of printf that's fairly close to conforming with
something like this:
int printf(char *args, ...) {
char *pos, *buffer;
unsigned long conversions = 0;
va_list rest;
int len;
for (pos = args; *pos; pos++)
if (*pos == '%' )
conversions++;
buffer = malloc(strlen(args) + 512*conversions);
if ( buffer == NULL)
return 0;
va_start(rest, args);
vsprintf(buffer, args, rest);
for (len=0; buffer[len]; len++) {
if (putchar(c, stdout) == EOF)
break;
free(buffer);
return len;
}
In particular, note that this sort of I/O can be cleanly separated
into distinct layers -- the part that formats the data doesn't need
to know anything about the I/O system at all, while the real I/O has
no need to know anything about formatting. As written above, printf
itself doesn't know about either one -- it's basically just a small
translation layer between the formatting (vsprintf) and the real
output routine (putchar).
> If i/o relies on compiler black magic (which is very likely),
> you can forget it; if it doesn't, at a minimum you still have to
> re-write the entire stdio library to be able to mix calls to your
> sprintf with calls to other stdio functions.
Nonsense. You can do output via the normal functions that handle one
character at a time. There are a few limitations (e.g. you can't
portably use ungetc inside of printf) but these are rarely any
problem at all.
> Leaving all that aside, stdio cannot be written in C unless the
> implementation provides a C interface to the low-level routines for
> actually talking to the file system.
It MUST do so -- that interface to the low-level routines is in fputc
and its close relatives. ALL the formatted output functions can be
written using only fputc to do output if necessary -- most will use
other "stuff" for the sake of efficiency, but there's no real
requirement for anything else.
--
Later,
Jerry.
The Universe is a figment of its own imagination.
In practice, sprintf() implementations do work with (the internals
of) a FILE object. The trick is that a FILE object is not a "file
object" but rather an "I/O descriptor data structure". Since
sprintf prints to a string, and sscanf scans from a string, one of
the sources and sinks for "I/O" is "a string".
Getting that to happen sometimes -- depending on the stdio and any
local extensions -- requires, and often "uses anyway" (for efficiency),
secrets of the implementation. My stdio does this to avoid having
to dynamically allocate a new FILE. (Otherwise it would be a
straightforward "funopen" call, and some private output-functions.)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.
Sure. But can we even remotely justify the assumption that vsprintf is
available, in a thread that asked for the code of the even simpler
function sprintf()? I strongly doubt it.
And that's not even beginning to address the quality of implementation
issue. An efficient implementation of the *printf() family of
functions almost directly requires a function like the traditional
_doprint() at the heart of it which can access the output 'stream'
directly --- be that a string, a file, or a counting mechanism for the
case of snprintf(). Buffering the output of a vsprintf() call and
sending the result to the output file doesn't cut it. At the minimum,
it makes it quite a lot harder than necessary to implement an
fprintf() that supports large output (beyond the minimum requirement
of 512 chars).
--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
You left out va_end - or is it not needed? I've run into some C
implementations that did require it, but am not sure about what the
current standard says about that.
Later,
AriL
--
Pain and disappointment are inevitable. Misery is optional.
Homepaged at http://www.angelfire.com/or/lukumies
Every va_start requires a matching va_end.
[ ... ]
> You left out va_end - or is it not needed? I've run into some C
> implementations that did require it, but am not sure about what the
> current standard says about that.
Yes, it's needed -- I was typing that in on the fly, and simply
screwed up; my apologies, but for the screwup and posting untested
code without a note to that effect.
--
Later,
Jerry.
The Universe is a figment of its own imagination.
[ ... ]
> In practice, sprintf() implementations do work with (the internals
> of) a FILE object. The trick is that a FILE object is not a "file
> object" but rather an "I/O descriptor data structure". Since
> sprintf prints to a string, and sscanf scans from a string, one of
> the sources and sinks for "I/O" is "a string".
I'm well aware that it's common. The original statement was that
sprintf needs to know details of the I/O implementation; it typically
does, but that's an entirely different question.
--
Later,
Jerry.
The Universe is a figment of its own imagination.
> Every va_start requires a matching va_end.
How about va_copy: does it require a va_end in the function where
va_copy is invoked, in the function where va_start is invoked, or
none at all?
n869 17.15.1:
"...Each invocation of the va_start or va_copy macros shall
be matched by a corresponding invocation of the va_end macro
in the function accepting a varying number of arguments."
--n
> n869 17.15.1:
>
> "...Each invocation of the va_start or va_copy macros shall
> be matched by a corresponding invocation of the va_end macro
> in the function accepting a varying number of arguments."
Was this wording left in the final standard? It seems to make
va_copy rather useless. Consider the following functions:
/* printf, so we get back to the subject :-) */
void my_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
my_vprintf(fmt, ap);
va_end(ap);
}
void my_vprintf(const char *fmt, va_list ap)
{
/* omitted */
}
Now, if my_vprintf needs to scan the argument list twice for
some reason, it could make a local copy with va_copy:
void my_vprintf(const char *fmt, va_list ap)
{
va_list copy;
va_copy(copy, ap);
/* omitted */
va_end(copy);
}
except va_end(copy) must be invoked in my_printf, not my_vprintf:
void my_printf(const char *fmt, ...)
{
va_list ap, *pcopy;
va_start(ap, fmt);
pcopy = my_vprintf(fmt, ap);
va_end(ap);
va_end(*pcopy);
}
va_list *my_vprintf(const char *fmt, va_list ap)
{
va_list copy;
va_copy(copy, ap);
/* omitted */
return ©
}
which is again wrong because the automatic variable is
deallocated before va_end is used on it. The copy could be made
static (not reentrant) or allocated on the heap (possibly running
out of memory), but the simplest way is to allocate it on the
stack of my_printf, which must know about it anyway:
void my_printf(const char *fmt, ...)
{
va_list ap, copy;
va_start(ap, fmt);
my_vprintf(fmt, ap, ©);
va_end(ap);
va_end(copy);
}
void my_vprintf(const char *fmt, va_list ap, va_list *pcopy)
{
va_copy(*pcopy, ap);
/* omitted */
}
which is no better than just invoking va_start twice in
my_printf. Is va_copy more useful in some other situation?
Or perhaps... does the standard allow the following code, which
does invoke va_end in the same function as va_start, although in
a different stack frame?
void my_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (fmt == NULL)
va_end(*va_arg(ap, va_list *));
else
my_vprintf(fmt, ap);
va_end(ap);
}
/* This can now be called from my_printf only. */
static void my_vprintf(const char *fmt, va_list ap)
{
va_list copy;
va_copy(copy, ap);
/* omitted */
my_printf(NULL, ©);
}
Finally, I'd like to learn about some platform where va_end isn't
a no-op: what its va_list contains, and what va_end does.
No, it was corrected to say "in the same function" instead of "in the
function accepting a varying number of arguments".
-Larry Jones
Is it too much to ask for an occasional token gesture of appreciation?!
-- Calvin