#ifdef _WINDOWS
# include <windows.h>
# include <winsock.h>
#endif
#include "tk.h"

/*
 *----------------------------------------------------------------------
 *
 * Tdp_WSAErrnoId --
 *
 *	Return a textual identifier for the current errno value.
 *
 * Results:
 *	This procedure returns a machine-readable textual identifier
 *	that corresponds to the current errno value (e.g. "EPERM").
 *	The identifier is the same as the #define name in errno.h.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
char *
Tdp_WSAErrnoId(error)
    int error;
{
    switch (error) {
    /*
     * Windows Sockets definitions of regular Microsoft C error constants
     */
    case WSAEINTR: return "WSAEINTR";
    case WSAEBADF: return "WSAEBADF";
    case WSAEACCES: return "WSAEACCES";
    case WSAEFAULT: return "WSAEFAULT";
    case WSAEINVAL: return "WSAEINVAL";
    case WSAEMFILE: return "WSAEMFILE";

    /*
     * Windows Sockets definitions of regular Berkeley error constants
     */
    case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
    case WSAEINPROGRESS: return "WSAEINPROGRESS";
    case WSAEALREADY: return "WSAEALREADY";
    case WSAENOTSOCK: return "WSAENOTSOCK";
    case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
    case WSAEMSGSIZE: return "WSAEMSGSIZE";
    case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
    case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
    case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
    case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
    case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
    case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
    case WSAEADDRINUSE: return "WSAEADDRINUSE";
    case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
    case WSAENETDOWN: return "WSAENETDOWN";
    case WSAENETUNREACH: return "WSAENETUNREACH";
    case WSAENETRESET: return "WSAENETRESET";
    case WSAECONNABORTED: return "WSAECONNABORTED";
    case WSAECONNRESET: return "WSAECONNRESET";
    case WSAENOBUFS: return "WSAENOBUFS";
    case WSAEISCONN: return "WSAEISCONN";
    case WSAENOTCONN: return "WSAENOTCONN";
    case WSAESHUTDOWN: return "WSAESHUTDOWN";
    case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
    case WSAETIMEDOUT: return "WSAETIMEDOUT";
    case WSAECONNREFUSED: return "WSAECONNREFUSED";
    case WSAELOOP: return "WSAELOOP";
    case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
    case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
    case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
    case WSAENOTEMPTY: return "WSAENOTEMPTY";
    case WSAEPROCLIM: return "WSAEPROCLIM";
    case WSAEUSERS: return "WSAEUSERS";
    case WSAEDQUOT: return "WSAEDQUOT";
    case WSAESTALE: return "WSAESTALE";
    case WSAEREMOTE: return "WSAEREMOTE";
    case WSAEDISCON: return "WSAEDISCON";
	
    /*
     * Extended Windows Sockets error constant definitions
     */
    case WSASYSNOTREADY: return "WSASYSNOTREADY";
    case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
    case WSANOTINITIALISED: return "WSANOTINITIALISED";

    /*
     * Error return codes from gethostbyname() and gethostbyaddr()
     * (when using the resolver). Note that these errors are
     * retrieved via WSAGetLastError() and must therefore follow
     * the rules for avoiding clashes with error numbers from
     * specific implementations or language run-time systems.
     * For this reason the codes are based at WSABASEERR+1001.
     * Note also that [WSA]NO_ADDRESS is defined only for
     * compatibility purposes.
     */

    /* Authoritative Answer: Host not found */
    case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";

    /* Non-Authoritative: Host not found, or SERVERFAIL */
    case WSATRY_AGAIN: return "WSATRY_AGAIN";

    /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
    case WSANO_RECOVERY: return "WSANO_RECOVERY";

    /* Valid name, no data record of requested type */
    case WSANO_DATA: return "WSANO_DATA";

    default:
	SetLastError(error);
    }
}
/*
 *----------------------------------------------------------------------
 *
 * Tdp_WSAError --
 *
 *	This procedure is typically called after Winsock calls
 *	return errors.  It stores machine-readable information about
 *	the error in $errorCode returns an information string for
 *	the caller's use.
 *
 * Results:
 *	The return value is a human-readable string describing the
 *	error, as returned by strerror.
 *
 * Side effects:
 *	The global variable $errorCode is reset.
 *
 *----------------------------------------------------------------------
 */

char *
Tdp_WSAError(interp, error)
    Tcl_Interp *interp;		/* Interpreter whose $errorCode variable
				 * is to be changed. */
    int error;
{
    char *id, *msg;

    id = Tdp_WSAErrnoId(error);
    msg = wsa_strerror(error);
    Tcl_SetErrorCode(interp, "Winsock", id, msg, (char *) NULL);
    return msg;
}

