variadic function, VARARGS68K and va_list parameter

This forum is for general developer support questions.
Post Reply
User avatar
abalaban
Beta Tester
Beta Tester
Posts: 456
Joined: Mon Dec 20, 2010 2:09 pm
Location: France
Contact:

variadic function, VARARGS68K and va_list parameter

Post by abalaban »

I'm still puzzled by the need to use the VARARGS68K macro.
At first I thought it was only required to be used in the event we need to have/call 68k compatible API.
But in the end it seems that any variadic function requires this tag, especially if it tries to pass the va_list to another function.
However sometimes it does not help, can somebody clarify that?

The code I'm trying to get working is the following:

Code: Select all

std::string vstrprintf(const char * fmt, va_list ap)
{
  char buf[512];
  vsnprintf(buf, sizeof(buf), fmt, ap);
  buf[sizeof(buf)-1] = 0;
  return buf;
}

VARARGS68K std::string strprintf(const char * fmt, ...)
{
  va_list ap; va_start(ap, fmt);
  std::string str = vstrprintf(fmt, ap);
  va_end(ap);
  return str;
}
The resulting binary crashes in newlib due to the call to vsnprintf() from vstrprintf() itself called from strprintf().
AmigaOne X1000 running AOS 4 beta
AmigaOne XE/G4
Amiga 1200/PPC 603e + BVision PPC
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 534
Joined: Sat Jun 18, 2011 4:12 pm
Location: Finland
Contact:

Re: variadic function, VARARGS68K and va_list parameter

Post by salass00 »

None of the <stdio.h> #?printf() use linear varargs calling convention so I don't know why you think you should use VARARGS68K there.

This is what I use in NTFS3G/Ext2FS to redirect calls to printf() to my own vkprintf() function:

Code: Select all

int printf(const char *fmt, ...) {
	va_list ap;
	va_start(ap, fmt);
	int retval = vkprintf(fmt, ap);
	va_end(ap);
	return retval;
}
User avatar
colinw
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 218
Joined: Mon Aug 15, 2011 10:20 am
Location: Brisbane, QLD. Australia.

Re: variadic function, VARARGS68K and va_list parameter

Post by colinw »

char buf[512];
-> return buf;

'buf' is an auto variable, it disappears when you leave the function.
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 534
Joined: Sat Jun 18, 2011 4:12 pm
Location: Finland
Contact:

Re: variadic function, VARARGS68K and va_list parameter

Post by salass00 »

colinw wrote:char buf[512];
-> return buf;

'buf' is an auto variable, it disappears when you leave the function.
Also the return value from the function should be a std::string object and not just a pointer to a char array.
User avatar
abalaban
Beta Tester
Beta Tester
Posts: 456
Joined: Mon Dec 20, 2010 2:09 pm
Location: France
Contact:

Re: variadic function, VARARGS68K and va_list parameter

Post by abalaban »

salass00 wrote:
colinw wrote:char buf[512];
-> return buf;

'buf' is an auto variable, it disappears when you leave the function.
Also the return value from the function should be a std::string object and not just a pointer to a char array.
Which it is: prototype of vstrprintf is

Code: Select all

std::string vstrprintf(const char * fmt, va_list ap)
As such it is automatically converted to std::string upon exit. Note that the std::string constructor copies the buffer, not just point to it, as such it should work.
It appears that my crash was due to something else: the caller of strprintf was doing a loop on a statically allocated array of structure. The problem was the initialization of this array that was done like one would do in C. While Initializer lists have been added to C++11 our current GCC does not seem to like them, adding a constructor to the structure and calling it instead of just passing the member values in braces solved the problem.

Nonetheless I'm still obligated to use the VARARGS68K macro for all my variadic functions else some integer gets wrongly displayed, it is probably an alignment problem, which is solved by the side-effect of declaring the function as a VARARGS68K :?:
AmigaOne X1000 running AOS 4 beta
AmigaOne XE/G4
Amiga 1200/PPC 603e + BVision PPC
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 534
Joined: Sat Jun 18, 2011 4:12 pm
Location: Finland
Contact:

Re: variadic function, VARARGS68K and va_list parameter

Post by salass00 »

abalaban wrote: As such it is automatically converted to std::string upon exit. Note that the std::string constructor copies the buffer, not just point to it, as such it should work.
Well if you are sure that it's automatically converted, I guess it's OK. If it was my code I would use an explicit conversion though and not rely on the compiler to do it for me, but then I don't write much C++ code.
Nonetheless I'm still obligated to use the VARARGS68K macro for all my variadic functions else some integer gets wrongly displayed, it is probably an alignment problem, which is solved by the side-effect of declaring the function as a VARARGS68K :?:
Did you recompile everything after removing VARARGS68K or did you still have some object files compiled with the old VARARGS68K prototype?

BTW this is how I implement my kprintf() in filesysbox.library/NTFS3G/Ext2FS and it is working perfectly there:

Code: Select all

#define GET_SYSBASE (*(struct ExecBase **)4)
#define GET_IEXEC ((struct ExecIFace *)GET_SYSBASE->MainInterface)

APTR debug_mutex;
static char debug_buffer[512];

int kprintf(const char *fmt, ...) {
	va_list ap;
	va_start(ap, fmt);
	int retval = vkprintf(fmt, ap);
	va_end(ap);
	return retval;
}

int vkprintf(const char *fmt, __VALIST args) {
	struct ExecIFace *IExec = GET_IEXEC;
	IExec->MutexObtain(debug_mutex);
	int retval = vsnprintf(debug_buffer, sizeof(debug_buffer), fmt, args);
	IExec->DebugPrintF("%s", debug_buffer);
	IExec->MutexRelease(debug_mutex);
	return retval;
}
If it didn't write numbers correctly I wouldn't have gotten very far with any of these projects ;-).
Post Reply