"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.

Reply via email to