weird but interesting code - needs help

V

vib

Hi there,

I am looking at this code for quite awhile, still don't any clue why
one wants to do it this way. It is about display message through UART
or COM port. Here is the code.

The calling code:
[1] MyDbgPrintf(("File Write Error\n"));

The called code:
[2] #define MyDbgPrintf(x) UART_Printf x

MOre, the body of UART_Printf:

[3]
void UART_Printf( const char *fmt, ... )
{
v_list ap;
char string[1024];

if( gUart_init == TRUE )
{
v_start( ap, fmt );
vsprintf( string, fmt, ap );
UART_SendString( string );
v_end( ap );
}
}

And the
[3]
void UART_SendString(char *string )
{
if( gUart_init == TRUE )
{
while( *string )
UART_SendByte( *string++ );
}
}

[4]
typedef int *v_list[1];

[5]
#define v_start(ap, parmN) (void)(*(ap) = __va_start(parmN))
[6]
#define v_end(ap) ((void)(*(ap) = 0))


Any comments?

what are [4], [5] [6] and why?

Thanks in advance.
 
W

Walter Roberson

I am looking at this code for quite awhile, still don't any clue why
one wants to do it this way. It is about display message through UART
or COM port.
v_list ap;
v_start( ap, fmt );
vsprintf( string, fmt, ap );
UART_SendString( string );
v_end( ap );
[4]
typedef int *v_list[1];
[5]
#define v_start(ap, parmN) (void)(*(ap) = __va_start(parmN))
[6]
#define v_end(ap) ((void)(*(ap) = 0))
Any comments?
what are [4], [5] [6] and why?


I suggest that you read the documentation about the elipsis
(...) prototype and the mechanisms by which one accesses variable
number of arguments. The relevant man page on unix-type systems
is often named stdarg

[4], [5], and [6] are all internal workings of a mechanism that
you should not be poking around in unless you are trying to
implement a C compiler. There are different expansions for them
on different systems.


By the way, the program has a potential buffer overflow problem.
If UART_Printf() is handed a parameter list that expands to more
than 1023 characters, the program will likely corrupt memory.
 
V

vib

Any benefits of using this method? Just thinking using a simple, easy
understand method, like writting to a circular buffer, and the TX empty
interrupt may read the circular buffer and send it to the UART. Simple
yet easy to implement.
 
W

Walter Roberson

Any benefits of using this method?

Which method? You did not quote any context, and I've read approximately
118 postings and 1063 email messages since your previous message.
Just thinking using a simple, easy
understand method, like writting to a circular buffer, and the TX empty
interrupt may read the circular buffer and send it to the UART. Simple
yet easy to implement.

UART... TX buffer... lemme rummage through my memory.

The layer you are neglecting is the -formatting- of the data to
write to the buffer. That's what the code you pointed to before
takes care of. It isn't until about 3 layers down that it gets to
the transmission of bytes to the UART, and it does that by way of
the UART_Send routine that we aren't shown the implementation of.
Whether the UART_Send works on a circular buffer or something else
is transparent to this level of code.

You shouldn't be looking at the va_* code as having anything to do
with the complicating of the routine. It -is- a "simple, easy understand"
method at the upper level. Your code just calls the debug
printf layer and passes whatever format string and argument that
it needs, and everything else is automagically taken care of.
You only need to get down to the lower level if you are the person
who has to implement the circular buffer or whatever...

If you -are- the person who needs to implement a circular buffer,
then consider exactly what the user interface would be. If the
circular buffer is partly full at the moment, and I ask to add
something to it, then suppose what I'm adding is too big to fit
into the buffer all at one time. What is your routine going to do then?
Reject the entire string that I want to add? Add what it can
and return the count (or buffer pointer) to the rest? Add what
it can at the moment, sleep a bit and add some more, and so on until
the entire message is inserted? One of the simplest insertion
mechanisms is to check to see if there is room for a byte,
add it if so, and if not then wait for a signal from the writing
routine saying it pulled something out of the buffer (or for
a sanity alarm in case that signal got lost somehow.) And that's
effectively the interface that this code has presented, with it's
preperation of the output string first and then looping sending each
byte in sequence using some unspecified transmission mechanism.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top