EmbeddedRelated.com
Forums
Memfault Beyond the Launch

printf function

Started by Martijn Broens April 1, 2003
Hi All,
 
I've been experimenting with the printf function and the usage of
va_list but I'm not sure if I understand it right.
 
int printf(const char *format, ...)                    /* Our main entry
*/
{
  va_list ap;
  int nr_of_chars;
 
  va_start(ap, format);      /* Variable argument begin */
  nr_of_chars = _formatted_write(format, put_one_char, (void *) 0, ap);
  va_end(ap);                /* Variable argument end */
  return nr_of_chars;        /* According to ANSI */
}
 
this is a copy of the printf. Does nr_of_chars actually contain the
number of chars formatted??? Because I don't see anything else but 1.
 
I'de like to use the va_list stuff for other serial related stuff so it
would be realy cool if nr_of_chars would contain the number of formatted
bytes.
 
 
thanks
Martijn Broens
 





Beginning Microcontrollers with the MSP430

usage of
> va_list but I'm not sure if I understand it
right.

Yu may want to check
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.10.html
for details.

/Roland

> I've been experimenting with the printf
function and the usage of
> va_list but I'm not sure if I understand it right.
>  
> int printf(const char *format, ...)                    /* Our main entry
> */
> {
>   va_list ap;
>   int nr_of_chars;
>  
>   va_start(ap, format);      /* Variable argument begin */
>   nr_of_chars = _formatted_write(format, put_one_char, (void *) 0, ap);
>   va_end(ap);                /* Variable argument end */
>   return nr_of_chars;        /* According to ANSI */
> }
>  
> this is a copy of the printf. Does nr_of_chars actually contain the
> number of chars formatted??? Because I don't see anything else but 1.
>  
> I'de like to use the va_list stuff for other serial related stuff so
it
> would be realy cool if nr_of_chars would contain the number of formatted
> bytes.

Yes, printf returns the number of bytes that has been printed.

For example, you can compiler and run the following program, and play
around with the format string (%x, %d etc.):

/---------------------
| #include <stdio.h>
| 
| int main()
| {
|   int x = printf("Hello %d!\n", -1);
|   printf("%d\n", x);
| }
\---------------------


You might want to be interested in the "vprintf" function.  This is a
quite unknown cousin to printf that accepts only two parameters, one
format string and a va_list.  This can be used inside other functions
that themselves have "..." arguments.  (All printf-related functions
have v-cousins like "vsprintf".)  For example:

/---------------------
| #include <stdio.h>
| #include <stdarg.h>
| 
| void foo(int x, ...)
| {
|   va_list args;
|   char const * fmt = 0;
| 
|   va_start(args, x);
| 
|   switch(x)
|   {
|   case 1: fmt = "%d\n";          break;
|   case 2: fmt = "%d:%d\n";       break;
|   case 3: fmt = "%d:%d:%d\n";    break;
|   case 4: fmt = "%d:%d:%d:%d\n"; break;
|   }
| 
|   if (fmt != 0)
|   {
|     vprintf(fmt, args);
|   }
| 
|   va_end(args);
| }
| 
| int main()
| {
|   foo(1,   10);
|   foo(2,   4711, 17);
|   foo(3,   123, 456, 789);
|   foo(4,   1, 2, 4, 8);
| }
\---------------------


    -- Anders


Hi Anders,
 
Thanks for the reply, i still don't know why nr_of_chars in my file
doesn't contain the actual number of bytes formatted. The problem with
vprintf is that you need to know how many bytes you've got, and that
just what I want to get rid of.
 
One of my wishes would be to create a printf look a like function that
send's a stream to the uarts or parallel busses.
 
thanks
Martijn Broens
 
-----Oorspronkelijk bericht-----
Van: Anders Lindgren [mailto:andersl@ande...] 
Verzonden: woensdag 2 april 2003 11:57
Aan: msp430@msp4...
Onderwerp: Re: [msp430] printf function
 

> I've been experimenting with the printf
function and the usage of
> va_list but I'm not sure if I understand it right.
>  
> int printf(const char *format, ...)                    /* Our main
entry
> */
> {
>   va_list ap;
>   int nr_of_chars;
>  
>   va_start(ap, format);      /* Variable argument begin */
>   nr_of_chars = _formatted_write(format, put_one_char, (void *) 0,
ap);
>   va_end(ap);                /* Variable argument
end */
>   return nr_of_chars;        /* According to ANSI */
> }
>  
> this is a copy of the printf. Does nr_of_chars actually contain the
> number of chars formatted??? Because I don't see anything else but 1.
>  
> I'de like to use the va_list stuff for other serial related stuff so
it
> would be realy cool if nr_of_chars would contain
the number of
formatted
> bytes.

Yes, printf returns the number of bytes that has been printed.

For example, you can compiler and run the following program, and play
around with the format string (%x, %d etc.):

/---------------------
| #include <stdio.h>
| 
| int main()
| {
|   int x = printf("Hello %d!\n", -1);
|   printf("%d\n", x);
| }
\---------------------


You might want to be interested in the "vprintf" function.  This is a
quite unknown cousin to printf that accepts only two parameters, one
format string and a va_list.  This can be used inside other functions
that themselves have "..." arguments.  (All printf-related functions
have v-cousins like "vsprintf".)  For example:

/---------------------
| #include <stdio.h>
| #include <stdarg.h>
| 
| void foo(int x, ...)
| {
|   va_list args;
|   char const * fmt = 0;
| 
|   va_start(args, x);
| 
|   switch(x)
|   {
|   case 1: fmt = "%d\n";          break;
|   case 2: fmt = "%d:%d\n";       break;
|   case 3: fmt = "%d:%d:%d\n";    break;
|   case 4: fmt = "%d:%d:%d:%d\n"; break;
|   }
| 
|   if (fmt != 0)
|   {
|     vprintf(fmt, args);
|   }
| 
|   va_end(args);
| }
| 
| int main()
| {
|   foo(1,   10);
|   foo(2,   4711, 17);
|   foo(3,   123, 456, 789);
|   foo(4,   1, 2, 4, 8);
| }
\---------------------


    -- Anders






 
<http://rd.yahoo.com/M$6920.2960106.4328965.1728375/D=egroupweb/S05
005378:HM/A13703/R=0/*http:/www.gotomypc.com/u/tr/yh/cpm/grp/300_06F/
g22lp?Target=mm/g22lp.tmpl> 

 
<http://us.adserver.yahoo.com/l?M$6920.2960106.4328965.1728375/D=egrou
pmail/S=:HM/A13703/randb5225343> 

.



">http://docs.yahoo.com/info/terms/>  Terms of Service. 





Hi Martijn,

> Thanks for the reply, i still don't know why
nr_of_chars in my file
> doesn't contain the actual number of bytes formatted. The problem with
> vprintf is that you need to know how many bytes you've got, and that
> just what I want to get rid of.

Strange, what version of the tools are you using?  (It seems to run
correctly in IAR 2.10A.)


> One of my wishes would be to create a printf look
a like function that
> send's a stream to the uarts or parallel busses.

There are two ways of doing this.

The first is to use "vsprintf", print to a string and then copy the
output to the uart.  For example:

/---
| #include <stdio.h>
| #include <stdarg.h>
| 
| /* Assuming that you have this somewhere. */
| void uart_send(char);
| 
| void uart_printf(char const * fmt, ...)
| {
|   va_list args;
|   int i, len;
|   char buf[256];
| 
|   va_start(args, fmt);
| 
|   len = vsprintf(buf, fmt, args);
| 
|   /*
|    * If your "vsprintf" returns the wrong length then you can
uncomment the
|    * line below.
|    */
| 
|   /* len = strlen(buf); */
| 
|   for (i = 0; i < len; ++i)
|   {
|     uart_send(buf[i]);
|   }
| 
|   va_end(args);
| }
\---


The other approach is to replace one of the underlying library
low-level output routines with a routine that sends the output to a
uart.  The advantage is that using this method all output can be
redirected a uart.

How this is done depends on the tools you are using and (for some
tools) the library you are using.  For the IAR tools version 1 you can
replace "putchar".  The same goes for version 2 if you are using the
"CLib library".  The following code will send all output to the uart,
regardless of how it is generated.

/---
| #include <stdio.h>
| 
| int putchar(int x)
| {
|   uart_send(x);
|   return x;
| }
|
| int main()
| {
|   printf("Hello\n");
| }
\---


In version 2 of the tools there is also another library, the "DLib
library".  This library support file-systems so the overriding
mechanisms are slightly more complicated.  You can either override
"__write" or "__writechar" (but not "putchar"!!),
depending on if you
would like to transmit a whole bunch of characters or just one at the
time.  (If overhead is required for each transmission then it might be
much more efficient to transmit a buffer.)

In addition the library support several open files so if you override
a small number of functions: "__open", "__close",
"__read" etc. then
you can send data to different hardware units, or you can use them to
implement a memory file system.  All higher level functions like
"fprintf" use the functions I mentioned above.

    -- Anders

How many people can be running 2.10 of the IAR tools?  Despite paying
huge sums to IAR for the privilege I have not been sent an official copy.  
The only way I got hold of it was to e-mail the support office and ask where 
it was - almost a month after IAR announced its release.
I was given the download URL.

My app is some 150 source files and 50K of compiled code.  Porting it
was not too difficult but I have abandoned the development under 2.10
because I hate the IAR editor and attempting to use an external one
involves repeatedly changing the edit mode from internal to external
and back again.  It is too painful.

Ian




>From: Anders Lindgren <andersl@ande...>
>Reply-To: msp430@msp4...
>To: msp430@msp4...
>Subject: Re: [msp430] printf function
>Date: Fri, 4 Apr 2003 10:31:00 +0200 (MEST)
>
>
>Hi Martijn,
>
> > Thanks for the reply, i still don't know why nr_of_chars in my
file
> > doesn't contain the actual number of bytes formatted. The problem
with
> > vprintf is that you need to know how many bytes you've got, and
that
> > just what I want to get rid of.
>
>Strange, what version of the tools are you using?  (It seems to run
>correctly in IAR 2.10A.)
>
>
> > One of my wishes would be to create a printf look a like function that
> > send's a stream to the uarts or parallel busses.
>
>There are two ways of doing this.
>
>The first is to use "vsprintf", print to a string and then copy
the
>output to the uart.  For example:
>
>/---
>| #include <stdio.h>
>| #include <stdarg.h>
>|
>| /* Assuming that you have this somewhere. */
>| void uart_send(char);
>|
>| void uart_printf(char const * fmt, ...)
>| {
>|   va_list args;
>|   int i, len;
>|   char buf[256];
>|
>|   va_start(args, fmt);
>|
>|   len = vsprintf(buf, fmt, args);
>|
>|   /*
>|    * If your "vsprintf" returns the wrong length then you can
uncomment 
>the
>|    * line below.
>|    */
>|
>|   /* len = strlen(buf); */
>|
>|   for (i = 0; i < len; ++i)
>|   {
>|     uart_send(buf[i]);
>|   }
>|
>|   va_end(args);
>| }
>\---
>
>
>The other approach is to replace one of the underlying library
>low-level output routines with a routine that sends the output to a
>uart.  The advantage is that using this method all output can be
>redirected a uart.
>
>How this is done depends on the tools you are using and (for some
>tools) the library you are using.  For the IAR tools version 1 you can
>replace "putchar".  The same goes for version 2 if you are using
the
>"CLib library".  The following code will send all output to the
uart,
>regardless of how it is generated.
>
>/---
>| #include <stdio.h>
>|
>| int putchar(int x)
>| {
>|   uart_send(x);
>|   return x;
>| }
>|
>| int main()
>| {
>|   printf("Hello\n");
>| }
>\---
>
>
>In version 2 of the tools there is also another library, the "DLib
>library".  This library support file-systems so the overriding
>mechanisms are slightly more complicated.  You can either override
>"__write" or "__writechar" (but not
"putchar"!!), depending on if you
>would like to transmit a whole bunch of characters or just one at the
>time.  (If overhead is required for each transmission then it might be
>much more efficient to transmit a buffer.)
>
>In addition the library support several open files so if you override
>a small number of functions: "__open", "__close",
"__read" etc. then
>you can send data to different hardware units, or you can use them to
>implement a memory file system.  All higher level functions like
>"fprintf" use the functions I mentioned above.
>
>     -- Anders


_________________________________________________________________
Use MSN Messenger to send music and pics to your friends 
http://www.msn.co.uk/messenger


hi Anders,
           I was able to use printf available in IAR code limited 
version, to print debug messages to 2x16 LCD. had to recompile 
the source and link it to the library module.

have't traced the history of your discussion on this  thread to 
understand if you have already done the above.
-vasu
 
--- In msp430@msp4..., Anders Lindgren <andersl@i...> wrote:
> 
> Hi Martijn,
> 
> > Thanks for the reply, i still don't know why nr_of_chars in my 
file
> > doesn't contain the actual number of
bytes formatted. The problem 
with
> > vprintf is that you need to know how many
bytes you've got, and 
that
> > just what I want to get rid of.
> 
> Strange, what version of the tools are you using?  (It seems to run
> correctly in IAR 2.10A.)
> 
> 
> > One of my wishes would be to create a printf look a like function 
that
> > send's a stream to the uarts or parallel
busses.
> 
> There are two ways of doing this.
> 
> The first is to use "vsprintf", print to a string and then copy
the
> output to the uart.  For example:
> 
> /---
> | #include <stdio.h>
> | #include <stdarg.h>
> | 
> | /* Assuming that you have this somewhere. */
> | void uart_send(char);
> | 
> | void uart_printf(char const * fmt, ...)
> | {
> |   va_list args;
> |   int i, len;
> |   char buf[256];
> | 
> |   va_start(args, fmt);
> | 
> |   len = vsprintf(buf, fmt, args);
> | 
> |   /*
> |    * If your "vsprintf" returns the wrong length then you can 
uncomment the
> |    * line below.
> |    */
> | 
> |   /* len = strlen(buf); */
> | 
> |   for (i = 0; i < len; ++i)
> |   {
> |     uart_send(buf[i]);
> |   }
> | 
> |   va_end(args);
> | }
> \---
> 
> 
> The other approach is to replace one of the underlying library
> low-level output routines with a routine that sends the output to a
> uart.  The advantage is that using this method all output can be
> redirected a uart.
> 
> How this is done depends on the tools you are using and (for some
> tools) the library you are using.  For the IAR tools version 1 you 
can
> replace "putchar".  The same goes for
version 2 if you are using the
> "CLib library".  The following code will send all output to the 
uart,
> regardless of how it is generated.
> 
> /---
> | #include <stdio.h>
> | 
> | int putchar(int x)
> | {
> |   uart_send(x);
> |   return x;
> | }
> |
> | int main()
> | {
> |   printf("Hello\n");
> | }
> \---
> 
> 
> In version 2 of the tools there is also another library, the "DLib
> library".  This library support file-systems so the overriding
> mechanisms are slightly more complicated.  You can either override
> "__write" or "__writechar" (but not
"putchar"!!), depending on if 
you
> would like to transmit a whole bunch of characters
or just one at 
the
> time.  (If overhead is required for each
transmission then it might 
be
> much more efficient to transmit a buffer.)
> 
> In addition the library support several open files so if you 
override
> a small number of functions: "__open",
"__close", "__read" etc. then
> you can send data to different hardware units, or you can use them 
to
> implement a memory file system.  All higher level
functions like
> "fprintf" use the functions I mentioned above.
> 
>     -- Anders



Memfault Beyond the Launch