Hi, As people reading the Jed mailing list knows, I'm trying to fix some glitches of Windows Jed. Sometimes this means changing something on Slang, I will try to put here things that are Slang-related. I want to declare two "private" slang functions (_pSLsnprintf and _pSLvsnprintf) public. Please note that: - Are already used externally (at least by Jed). - Are useful as wrappers to hide system differences: the return code changes from system to system, ans some old systems doesn't have an implementation at all. The current implementation has some problems: Slang expects that system version, if exists, return EOF, but this is not tested by configure, so for example or recent linuxes (with glibc >= 2.1) this is not true, as from that version they follow the C99 standard, so the return value is the size needed for a correct output (the old glibc versions, and also Visual Studio 6, returns -1). Quoting man snprintf: ------- quote begin Return value Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings). The functions snprintf and vsnprintf do not write more than size bytes (including the trailing '\0'). If the output was truncated due to this limit then the return value is the number of characters (not including the trailing '\0') which would have been writ- ten to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated. (See also below under NOTES.) If an output error is encountered, a neg- ative value is returned. [SNIP] NOTES The glibc implementation of the functions snprintf and vsnprintf conforms to the C99 standard, i.e., behaves as described above, since glibc version 2.1. Until glibc 2.0.6 they would return -1 when the output was truncated. [SNIP] Concerning the return value of snprintf, the SUSv2 and the C99 standard contradict each other: when snprintf is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. -------- quote end MSDN October 2004 says: -------- quote begin Return Value _snprintf returns the number of bytes stored in buffer, not counting the terminating null character. If the number of bytes required to store the data exceeds count, then count bytes of data are stored in buffer and a negative value is returned. Security Note Ensure that format is not a user-defined string. This function does not guarantee NULL termination, so ensure it is followed by sz[ ARRAYSIZE(sz) - 1] = 0. -------- quote end Note that while for most systems EOF == -1, this is not mandatory. So I propose to: - rename the functions to SLvsnprintf and SLsnprintf. - declare both on slang.h - define SLvsnprintf as returning -1 on error, and handle internally systems returning size. - keep the poors man implementation for systems without vsnprintf. - implement SLsnprintf using SLvsnprintf. I still things that the C99 standard is the correct way to do this, but if the system snprintf returns -1 externally we can only guess the real buffer size, so implementing SLsnprintf as returning the required buffer size is difficult, complex and time-consuming. The attached patch against SLang-pre2-r5 does: - Removes definitions from _slang.h - Adds new ones to slang.h - reimplement functions. - Changes all the callers within slang the the new names. - changes all the return value tests against EOF to -1. - #define HAVE_SNPRINTF and HAVE_VSNPRINT in slconfig.h if _MSC_VER is defined (at least Visual Studio 6 has these). I don't know if some system has a working snprintf implementation but not a vsnprintf. If suvh a beast exists, on those system we loose the snprintf protection. I we care about this we can add to slang.h something like: #if defined(HAVE_SNPRINTF) && !defined(HAVE_VSNPRINTF) /* avoid using the unsafe SLvsnprintf to implement SLsnprintf as we have a working snprintf */ #define SLsnprintf snprintf #else extern int SLvsnprintf (char *buf, unsigned int buflen, char *fmt, va_list ap); #endif And exclude compilation definition. But this way we can only hope that the system snprintf return -1 on buffer not big enough. Comments? Later, Dino
Attachment:
slang-export-SLsnprintf.diff
Description: Binary data
_______________________________________________ To unsubscribe, visit http://jedsoft.org/slang/mailinglists.html