Does gcc for Due Support va_args?

I need to implement a printf-like function, with variable argument list. This should be trivial, using vsprintf, but I can’t get it to compile. Here is the funciton:

void ATCStateMachine::DebugMsg(const char *fmt, ...)
{
	if (DebugEnable)
	{
		  char s[256];
		  va_list  args;
		  
		  va_start (args, fmt);
		  vsprintf (s, fmt, args);
		  pCmdQueue->PushDebug(new ATCStringMessage(DebugSrc, DebugDest, s));
		  va_end (args);		
	}
}

Sadly, the compiler seems not to know va_list, even though I do # include <stdarg.h>. It doesn’t seem to have a problem with va_start, va_end, or vsprintf.

Compiling ‘SuperATC’ for ‘Arduino Due (Programming Port)’
Build folder: file:///C:/Users/RayL/AppData/Local/V.Micro/Arduino/Builds/SuperATC/arduino_due_x_dbg
ATCStateMachine.cpp:In member function ‘void ATCStateMachine::DebugMsg(const char*, …)’
ATCStateMachine.cpp:50:5: error: ‘va_list’ was not declared in this scope
ATCStateMachine.cpp:50:14: error: expected ‘;’ before ‘args’
ATCStateMachine.cpp:52:15: error: ‘args’ was not declared in this scope
Error compiling

Any ideas?

Regards,
Ray L.

On a related note....

How can I make the compiler save the pre-processor output, so I can see what is actually getting compiled? That might give me a clue why va_list is not working.

Regards,
Ray L.

Of course you can use va_args. Just include the relevant header files.

One of the side'-effects of the Arduino "build" process is that the punter does not realise which files are included.

Since Arduino is largely C++, it abhors the idea of variadic functions. It discourages their use but it does not prevent it. e.g. it omits including stdio.h

David.

How can I make the compiler save the pre-processor output, so I can see what is actually getting compiled?

Configure the IDE for verbose compilation output, copy and paste the compile command in a terminal/command window, editing to replace -c with -E and -o xxxx with something more appropriate.

david_prentice:
Of course you can use va_args. Just include the relevant header files.

One of the side'-effects of the Arduino "build" process is that the punter does not realise which files are included.

Since Arduino is largely C++, it abhors the idea of variadic functions. It discourages their use but it does not prevent it. e.g. it omits including stdio.h

David.

Except, as I've shown it does not work. va_list ends up undefined, while va_args, va_start and va_end ARE defined, as shown in the error messages I included in my post.

Have you actually used them on Due?

Regards,
Ray L.

westfw:
Configure the IDE for verbose compilation output, copy and paste the compile command in a terminal/command window, editing to replace -c with -E and -o xxxx with something more appropriate.

Is there a way to make those changes in the full build process? A configuration file that can be changed perhaps?

Regards,
Ray L.

Below is a trivial test program that does not compile. There is clearly something non-standard in the Due implementation, as this compiles just fine when targeted to ANY AVR-based Arduino.

#include <Arduino.h>
#include <stdarg.h>


void setup() 
{
	Serial.begin(115200);
}

void loop() 
{

}

void DebugMsg(const char *fmt, ...)
{
		char s[256];
		va_list  args;
		  
		va_start (args, fmt);
		vsprintf (s, fmt, args);
		Serial.print(s);
		va_end (args);		
}

Compiling ‘BlivetSketch’ for ‘Arduino Due (Programming Port)’
Build folder: file:///C:/Users/RayL/AppData/Local/V.Micro/Arduino/Builds/BlivetSketch/arduino_due_x_dbg
BlivetSketch.ino:In function ‘void DebugMsg(const char*, …)’
BlivetSketch.ino:21:3: error: ‘va_list’ was not declared in this scope
BlivetSketch.ino:21:12: error: expected ‘;’ before ‘args’
BlivetSketch.ino:23:13: error: ‘args’ was not declared in this scope
Error compiling

Regards,
Ray L.

Your program compiles with Arduino version 1.6.5
It also runs in v.micro where it shows definition of va_list as being in stdar.h

George

Well, I tried your code on a UNO. Of course, nothing happened. You do not even print a sign-on message. You do not call your DebugMsg() function.

So I produced a minimal sketch that does do something:

#include <Arduino.h>
#include <stdio.h>
#include <stdarg.h>

void DebugMsg(const char *fmt, ...)
{
    char s[256];
    va_list  args;

    va_start (args, fmt);
    vsprintf (s, fmt, args);
    Serial.print(s);
    va_end (args);
}

void setup()
{
    Serial.begin(9600);
    Serial.println("va_args.  Ray Livingston");
}

void loop()
{
    DebugMsg("%s %04x %f\n", "david", 0x1234, 56.78);
    delay(1000);
}

On a UNO, it says “david 1234 ?”
On a DUE, it says “david 1234 56.780000”
On a M0_Pro, it says “david 1234”

These differences are down to the way that the libprintf_flt.a is linked.
All the boards can manage floating point but it is probably too much bother to configure the build process.

You also need to be aware of the different size int on each platform. So you should be very specific with your “l” qualifiers.

David.

george4657:
Your program compiles with Arduino version 1.6.5
It also runs in v.micro where it shows definition of va_list as being in stdar.h

George

Compiling for Due? Because I am running 1.6.5, and it compiles fine for me for anything BUT a Due, but will not compile for Due.

Regards,
Ray L.

david_prentice:
Well, I tried your code on a UNO. Of course, nothing happened. You do not even print a sign-on message. You do not call your DebugMsg() function.

So I produced a minimal sketch that does do something:

#include <Arduino.h>

#include <stdio.h>
#include <stdarg.h>

void DebugMsg(const char *fmt, …)
{
    char s[256];
    va_list  args;

va_start (args, fmt);
    vsprintf (s, fmt, args);
    Serial.print(s);
    va_end (args);
}

void setup()
{
    Serial.begin(9600);
    Serial.println(“va_args.  Ray Livingston”);
}

void loop()
{
    DebugMsg("%s %04x %f\n", “david”, 0x1234, 56.78);
    delay(1000);
}



On a UNO, it says "david 1234 ?"
On a DUE, it says "david 1234 56.780000"
On a M0_Pro, it says "david 1234"

These differences are down to the way that the libprintf_flt.a is linked.
All the boards can manage floating point but it is probably too much bother to configure the build process.

You also need to be aware of the different size int on each platform. So you should be very specific with your "l" qualifiers.

David.

I don’t care that the sample program doesn’t actually do anything. I already stated that it compiles just fine for ANY AVR-based Arduino. So, running it on an Uno is no help. I CANNOT get it to compile when the target is Due, as va_list is undefined. This is a Due-only problem.

Regards,
Ray L.

david_prentice:
Well, I tried your code on a UNO. Of course, nothing happened. You do not even print a sign-on message. You do not call your DebugMsg() function.

So I produced a minimal sketch that does do something:

#include <Arduino.h>

#include <stdio.h>
#include <stdarg.h>

void DebugMsg(const char *fmt, …)
{
   char s[256];
   va_list  args;

va_start (args, fmt);
   vsprintf (s, fmt, args);
   Serial.print(s);
   va_end (args);
}

void setup()
{
   Serial.begin(9600);
   Serial.println(“va_args.  Ray Livingston”);
}

void loop()
{
   DebugMsg("%s %04x %f\n", “david”, 0x1234, 56.78);
   delay(1000);
}



On a UNO, it says "david 1234 ?"
On a DUE, it says "david 1234 56.780000"
On a M0_Pro, it says "david 1234"

These differences are down to the way that the libprintf_flt.a is linked.
All the boards can manage floating point but it is probably too much bother to configure the build process.

You also need to be aware of the different size int on each platform. So you should be very specific with your "l" qualifiers.

David.

I don’t care that the sample program doesn’t actually do anything. I already stated that it compiles just fine for ANY AVR-based Arduino. So, running it on an Uno is no help. I CANNOT get it to compile when the target is Due, as va_list is undefined. This is a Due-only problem.

What version of Arduino IDE were you using for your Due compile? I am using 1.6.5.

Regards,
Ray L.

Hmmmm… changing va_list to __gnuc_va_list works, but should not be necessary:

#include <Arduino.h>
#include <stdarg.h>


void DebugMsg(const char *fmt, ...)
{
	char s[256];
	__gnuc_va_list  args;
		  
	va_start (args, fmt);
	vsprintf (s, fmt, args);
	Serial.print(s);
	va_end (args);		
}


void setup() 
{
	Serial.begin(115200);
}


void loop() 
{
        DebugMsg("Hello, world\n");
}

Regards,
Ray L.

I told you that I built and ran it on a Uno, Due, M0.
I did not tell you that I used v1.6.5 IDE on a Win7-64 PC.

No, I had no problems with va_list
Yes, I had to declare the variadic function before calling it. The Arduino kludging does not do it for you.

Building a program that does not do anything is unwise (tm).
GCC will simply remove any uncalled code. So you don't even know if it would build or link.

David.

david_prentice:
I told you that I built and ran it on a Uno, Due, M0.
I did not tell you that I used v1.6.5 IDE on a Win7-64 PC.

No, I had no problems with va_list
Yes, I had to declare the variadic function before calling it. The Arduino kludging does not do it for you.

Building a program that does not do anything is unwise (tm).
GCC will simply remove any uncalled code. So you don't even know if it would build or link.

David.

Your code, exactly as you posted it does NOT compile here, It gives the exact same errors I get with mine - va_list is undefined.

Regards,
Ray L.

RayLivingston:
Your code, exactly as you posted it does NOT compile here, It gives the exact same errors I get with mine - va_list is undefined.

Regards,
Ray L.

It compiles fine for me when targeting the Due. In fact, I've been using these variadic functions in GEVCU for years. It has always compiled perfectly well. You have to have something really messed up with your Arduino installation because it works fine for everyone else. I know that's probably not what you want to hear but it really does compile fine so the problem is on your end.

Well, I showed you mine. Perhaps you should say what IDE and what o-s you are using.

When you add the Due package to your IDE, it will use a specific build of ARM compiler and Arduino core. Arduino tend to use their own local copies of a Toolset. And generally, out of date versions.

I can only think that you and I have different ARM tools.

David.

david_prentice:
Well, I showed you mine. Perhaps you should say what IDE and what o-s you are using.

When you add the Due package to your IDE, it will use a specific build of ARM compiler and Arduino core. Arduino tend to use their own local copies of a Toolset. And generally, out of date versions.

I can only think that you and I have different ARM tools.

David.

I have IDE v1.6.5 installed. It's been working perfectly for months in every other way - my current application is up to almost 250K of object code. It clearly is something about my particular install, since it works for you. However, at least replacing "va_list" with "__gnuc_va_list" compiles and works perfectly.

My compiler is v4.8.3-2014q1. The SAM3X board support package is v1.6.4, which appears to be the latest version.

Regards,
Ray L.

My compile of sample program was on Arduino 1.6.5 ide and also in visual micro , visual studio 213 version in windows 10 64 bit

Checking path to stdarg.h I get:
C:\Users\GEORGE\AppData\Roaming\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\lib\gcc\arm-none-eabi\4.8.3\include\stdarg.h

Check that you have this file

Yes, I have that file. If not, it wouldn't be finding definitions for va_start and va_end.

Regards,
Ray L.