va_list Undefined...

I’ve been trying to create a printf-replacement, using vsprintf. Unfortunately, when building for Due, va_list ends up undefined. It compiles fine for any AVR-based board, so it’s seemingly a problem in the Due package. I’ve posted this on the Due forum, but there’s very little traffic over there, so I’ve gotten no help so far, and am hoping someone over here has used it.

Below is a trivial test program that does not compile when targeted to Due.

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


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

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

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.

I ran 'grep va_list *' on the header files for arm-gcc and found the following:

__builtin_va_list

__gnuc_va_list

We deliberately do not define va_list when called from
va_list. stdio.h needs to have access to that data type,
but must not use that name. It should use the name __gnuc_va_list,

typedef __gnuc_va_list va_list;

and on and on...

Perhaps this will be of some use to you.

Get a copy of grep for your machine as it also tells you the name of the file where the word or phrase was found.

Documentation for gcc will have information about the builtins.

tf68:
I ran 'grep va_list *' on the header files for arm-gcc and found the following:

__builtin_va_list

__gnuc_va_list

We deliberately do not define va_list when called from
va_list. stdio.h needs to have access to that data type,
but must not use that name. It should use the name __gnuc_va_list,

typedef __gnuc_va_list va_list;

and on and on...

Perhaps this will be of some use to you.

Get a copy of grep for your machine as it also tells you the name of the file where the word or phrase was found.

Documentation for gcc will have information about the builtins.

Yeah, I found that file, but it is unintelligible, as the code is knee-deep in #ifdefs. I could not find any references to to make it work. But it DOES work with the AVR Arduinos. It's only the Due compiler which is different. Makes no sense. I've used vsprintf in many dozens of compilers since the very early '80s, and never come across this.

Regards,
Ray L.

For reasons I cannot begin to understand, if I change "va_list" to "__gnuc_va_list", it compiles without error...

Regards,
Ray L.

I think this may be what you want.

#include

Yeah somewhere in all that loony nonsense va_list gets defined as __gnuc_va_list.

tf68:
I think this may be what you want.

#include

Yeah somewhere in all that loony nonsense va_list gets defined as __gnuc_va_list.

Doesn’t work for me - I still get the same errors about va_list being undefined. But using __gnuc_va_list compiles and works. I wish I understood why…

Regards,
Ray L.

Just for grins I tried your test program. It compiles on my system without issue (I did move the DebugMsg function definition above setup otherwise it complained about DebugMsg being undefined when it was after loop). With or without #include or #include <stdarg.h>.

The IDE is Arduino-1.6.1, the arm compiler is gcc-arm-none-eabi-4.8.3-2014q1 and it is running on Linux. I don’t use the Due and this is the last IDE on my system that supported the Due “out of the box”. So we have even more of a mystery, love it.

Just to make things worse, there is one guy on the Due forum who CAN build it without error using the same IDE version I'm using. But for me, I have to use __gnuc_va_list...

Regards,
Ray L.

Have a look at my PrintEx library if you like, I have a custom printf implementation (plus many other features like streaming in/out, chain-able methods). Even if you don’t want to use it, you can see how I’ve done the implementation. You can download it in the lib manager and see its features & code here: PrintEx overview

This uses va_args and works fine on the Due.

#include <PrintEx.h>

PrintEx serial = Serial;

void setup() {
  Serial.begin(9600);
  serial.printf( "%30n\nA formatted float: %08.4f\n%30n", '-', 3.1415f, '-' );
}

void loop() {}

Produces:

** **------------------------------ A formatted float: 003.1415 ------------------------------** **

I have only found that I needed to get my lib to add cstdargs for the zero. Your code works fine in the latest revisions. You should try at least 1.6.5, or the latest hourly build of 1.6.6.

Your example compiles fine here on both Mac and WXP, at least after moving DebugMsg() before setup().

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

You know, that doesn't look at all like the output I get, even if I intentionally introduce an error by using "va_listx" instead of "va_list." How did you say your environment was set up? Are you using one of the interim builds rather than a release? What does the "verbose" compilation look like?

Build folder: file:///C:/Users/RayL/AppData/Local/V.Micro/Arduino/Builds/BlivetSketch/arduino_due_x_dbg

I've never seen a nice compact and helpful message like that! Or a path like that. Um, wait a second - are you using Visual Micro rather than the Arduino IDE?