Could Rvsnprintf (in src/main/errors.c) be added to the R API with prototype in include/R_ext/Print.h say? Here's my problem. I'm trying to write some code that is not totally tied to R. Hence I want R style error messaging to be isolated in a small module. I do not want #include <R.h> and calls to error (Rf_error) in most of my code. Hence I want to write a module with something like ----- begin code snippet ----- #include <stdarg.h> #include <stdio.h> #include <R.h> #define BUFSIZE 1024 void die(const char *format, ...) { char buf[BUFSIZE]; va_list arg; va_start(arg, format); vsnprintf(buf, BUFSIZE, format, arg); va_end(arg); buf[BUFSIZE - 1] = '\0'; error(buf); } ----- end code snippet ----- But that's not portable because vsnprintf isn't. You've already made a big effort to work around nonportability of vsnprintf, but don't make it available in the API. Why not? If I could change vsnprintf to Rvsnprintf above, then I wouldn't have to do some horrible autoconf song and dance that probably wouldn't be completely portable anyway. Or is there a better solution I haven't seen? -- Charles Geyer Professor, School of Statistics University of Minnesota charlie@stat.umn.edu
On Fri, 13 May 2005, Charles Geyer wrote:> Could Rvsnprintf (in src/main/errors.c) be added to the R API > with prototype in include/R_ext/Print.h say? > > Here's my problem. I'm trying to write some code that is not > totally tied to R. Hence I want R style error messaging to > be isolated in a small module. I do not want #include <R.h> > and calls to error (Rf_error) in most of my code. > Hence I want to write a module with something like > > ----- begin code snippet ----- > #include <stdarg.h> > #include <stdio.h> > #include <R.h> > > #define BUFSIZE 1024 > > void die(const char *format, ...) > { > char buf[BUFSIZE]; > va_list arg; > > va_start(arg, format); > vsnprintf(buf, BUFSIZE, format, arg); > va_end(arg); > buf[BUFSIZE - 1] = '\0'; > error(buf); > } > ----- end code snippet ----- > > But that's not portable because vsnprintf isn't. > You've already made a big effort to work around nonportability of > vsnprintf, but don't make it available in the API. Why not? > > If I could change vsnprintf to Rvsnprintf above, then I wouldn't > have to do some horrible autoconf song and dance that probably wouldn't > be completely portable anyway. > > Or is there a better solution I haven't seen?R guarantees to have *vsnprintf* available. Putting things in the API is a one-way decision and ties our hands for ever. Rvsnprintf is not even exported from errors.c: it is static and just a convenience wrapper. About all a user package needs to do is AC_CHECK_DECLS([vsnprintf]) and in your code snippet #if defined(HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); #endif However, AFAIK all known R platforms do have vsnprintf these days: the MinGW compiler used on Windows gained it within the last year. -- Brian D. Ripley, ripley@stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On 14-May-2005, Prof Brian Ripley wrote: | R guarantees to have *vsnprintf* available. Putting things in the API is | a one-way decision and ties our hands for ever. Rvsnprintf is not even | exported from errors.c: it is static and just a convenience wrapper. | | About all a user package needs to do is | | AC_CHECK_DECLS([vsnprintf]) | | and in your code snippet | | #if defined(HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF | extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); | #endif | | However, AFAIK all known R platforms do have vsnprintf these days: the | MinGW compiler used on Windows gained it within the last year. Is checking for vsnprintf availability sufficient, or should one also check for versions that behave differently? As I recall, different versions of vsnprintf return different values when a buffer overflow occurs. Standard versions return the number of characters that would have been in the string (not including the terminating nul) if the buffer had been big enough, but older versions (apparently including glibc prior to 2.1) simply return -1 if the buffer is too small. Is it worth trying to handle these differences? Or at least detect the broken vsnprintf and fail to build? jwe
Apparently Analagous Threads
- help with gotoExitingHandler(R_NilValue, call, entry); . Implementation of error handling internally
- segfault on write.dcf with gzfile connection
- When collected warnings exceeds 50
- Seg fault when installing package from bad repository
- vsnprintf_s and vsnprintf