"Gisle Vanem" <[EMAIL PROTECTED]> writes:
>> There is another possible approach. We already #define read and write
>> to call Winsock stuff. We could add some more magic so that they and
>> other Winsock invocations automatically set errno to last error value,
>> translating Windows errors to errno errors.
>
> Then all Winsock functions must be wrapped in such macro.
> E.g (untested):
> #define SOCK_SELECT(fd,rd,wr,ex,tv) ( \
> int _rc = select (fd,rd,wr,ex,tv), \
> (int)(WSAGetLastError() ? (errno = WSAGetLastError()) : (0)), \
> _rc)
>
> which could get messy; hard to return with a value from such a
> macro.
How about:
#ifdef WINDOWS
# define select(a, b, c, d) windows_select (a, b, c, d)
#endif
windows_select can be a function defined in mswindows.c that calls
select, performs the necessary error-handling magic, and (easily)
returns a value. BTW errno should only be modified if _rc<0.
>> static struct errentry errtable[] = {
>> { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
>> { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
>
> XEmacs is probably using native Win functions (e.g CreateFile
> instead of fopen), so it needs to map them to Unix errnos.
I believe it calls them in some places, and there it calls
mswindows_set_last_errno to fix up errno in case the callers inspect
it. This is similar to the strategy I'd like to use in Wget.
> Wget only uses ANSI/Winsock functions, so only WS errors need
> attention.
OK.
> Besides, on Windows there is no suiteable <errno.h> value for
> e.g. ENOTCONN; we must use the <winsock*.h> value WSAENOTCONN. So
> the XEmacs method wouldn't work.
Note that we could always add a version of strerror that supports
those. For example:
/* mswindows.h */
enum { X_ERRBASE = 10000, X_ENOTCONN = 10001, ... };
#ifndef ENOTCONN
# define ENOTCONN X_ENOTCONN
#endif
...
#define strerror(n) windows_strerror (n)
/* mswindows.c */
#undef strerror /* we want the real one here */
const char *
windows_strerror (int err)
{
/* Leave the standard ones to strerror. */
if (err < X_ERRBASE)
return strerror (err);
/* Handle the unsupported ones manually. */
switch (err)
{
case X_ENOTCONN:
return "Connection refused";
...
default:
abort ();
}
return NULL;
}
I know this looks like an unnecessary contortion at first, but Wget
*is* targeted to primarily support Unix-like OS'es, specifically GNU.
In this case I believe it makes sense to make the Windows-specific
code more complex to reduce the complexity in the code that assumes
Unix API's.