/* * Copyright (c) 2002-2011 by XMLVM.org * * Project Info: http://www.xmlvm.org * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include "xmlvm.h" #include "xmlvm-hy.h" const char* errorMessage (I_32 errorCode) { PortlibPTBuffers_t ptBuffers; ptBuffers = hyport_tls_peek (); if (0 == ptBuffers->errorMessageBufferSize) { ptBuffers->errorMessageBuffer = XMLVM_ATOMIC_MALLOC(HYERROR_DEFAULT_BUFFER_SIZE); if (NULL == ptBuffers->errorMessageBuffer) { return ""; } ptBuffers->errorMessageBufferSize = HYERROR_DEFAULT_BUFFER_SIZE; } /* Copy from OS to ptBuffers */ #if !defined(ZOS) strerror_r(errorCode, ptBuffers->errorMessageBuffer, ptBuffers->errorMessageBufferSize); #else /* Do not have strerror_r on z/OS so use port library function instead */ portLibrary->str_printf(portLibrary, ptBuffers->errorMessageBuffer, ptBuffers->errorMessageBufferSize, strerror(errorCode)); #endif /* ZOS */ ptBuffers->errorMessageBuffer[ptBuffers->errorMessageBufferSize - 1] = '\0'; return ptBuffers->errorMessageBuffer; } static const char* swapMessageBuffer (PortlibPTBuffers_t ptBuffers, const char *message) { char *tempBuffer = ptBuffers->reportedMessageBuffer; U_32 tempBufferSize = ptBuffers->reportedMessageBufferSize; if (message == NULL) { return ""; } /* Can't swap unknown message buffer */ if (message != ptBuffers->errorMessageBuffer) { return message; } /* Save reported information */ ptBuffers->reportedErrorCode = ptBuffers->portableErrorCode; ptBuffers->reportedMessageBuffer = ptBuffers->errorMessageBuffer; ptBuffers->reportedMessageBufferSize = ptBuffers->errorMessageBufferSize; if (tempBufferSize > 0) { tempBuffer[0] = '\0'; } /* Clear pending fields ready for next error */ ptBuffers->portableErrorCode = 0; ptBuffers->errorMessageBuffer = tempBuffer; ptBuffers->errorMessageBufferSize = tempBufferSize; return ptBuffers->reportedMessageBuffer; } void* hyport_tls_get () { java_lang_Thread* curThread = (java_lang_Thread*) java_lang_Thread_currentThread__(); if (curThread->fields.java_lang_Thread.ptBuffers_ == JAVA_NULL) { curThread->fields.java_lang_Thread.ptBuffers_ = XMLVM_MALLOC(sizeof(PortlibPTBuffers_struct)); XMLVM_BZERO(curThread->fields.java_lang_Thread.ptBuffers_, sizeof(PortlibPTBuffers_struct)); } return curThread->fields.java_lang_Thread.ptBuffers_; } void* hyport_tls_peek () { java_lang_Thread* curThread = (java_lang_Thread*) java_lang_Thread_currentThread__(); return curThread->fields.java_lang_Thread.ptBuffers_; } const char* hyerror_last_error_message () { PortlibPTBuffers_t ptBuffers; /* Was an error saved ? */ ptBuffers = hyport_tls_peek (); if (NULL == ptBuffers) { return ""; } /* New error ? */ if (ptBuffers->portableErrorCode != 0) { const char *message = NULL; /* Customized message stored ? */ if (ptBuffers->errorMessageBufferSize > 0) { if ('\0' != ptBuffers->errorMessageBuffer[0]) { message = ptBuffers->errorMessageBuffer; } } /* Call a helper to get the last message from the OS. */ if (message == NULL) { message = errorMessage (ptBuffers->platformErrorCode); } /* Avoid overwrite by internal portlib errors */ return swapMessageBuffer (ptBuffers, message); } /* Previous message stored ? */ if (ptBuffers->reportedMessageBufferSize > 0) { if ('\0' != ptBuffers->reportedMessageBuffer[0]) { return ptBuffers->reportedMessageBuffer; } } /* No error. */ return ""; } I_32 hyerror_last_error_number () { PortlibPTBuffers_t ptBuffers; /* get the buffers, return failure if not present */ ptBuffers = hyport_tls_peek (); if (NULL == ptBuffers) { return 0; } /* New error ? */ if (ptBuffers->portableErrorCode != 0) { return ptBuffers->portableErrorCode; } else { return ptBuffers->reportedErrorCode; } } I_32 hyerror_set_last_error (I_32 platformCode, I_32 portableCode) { PortlibPTBuffers_t ptBuffers; /* get the buffers, allocate if necessary. * Silently return if not present, what else would the caller do anyway? */ ptBuffers = hyport_tls_get (); if (NULL == ptBuffers) { return portableCode; } /* Save the last error */ ptBuffers->platformErrorCode = platformCode; ptBuffers->portableErrorCode = portableCode; /* Overwrite any customized messages stored */ if (ptBuffers->errorMessageBufferSize > 0) { ptBuffers->errorMessageBuffer[0] = '\0'; } return portableCode; } I_32 hyerror_set_last_error_with_message (I_32 portableCode, const char *errorMessage) { PortlibPTBuffers_t ptBuffers; U_32 requiredSize; /* get the buffers, allocate if necessary. * Silently return if not present, what else would the caller do anyway? */ ptBuffers = hyport_tls_get (); if (NULL == ptBuffers) { return portableCode; } /* Save the last error */ ptBuffers->platformErrorCode = -1; ptBuffers->portableErrorCode = portableCode; /* Store the message, allocate a bigger buffer if required. Keep the old buffer around * just in case memory can not be allocated */ requiredSize = strlen (errorMessage) + 1; requiredSize = requiredSize < HYERROR_DEFAULT_BUFFER_SIZE ? HYERROR_DEFAULT_BUFFER_SIZE : requiredSize; if (requiredSize > ptBuffers->errorMessageBufferSize) { char *newBuffer = XMLVM_ATOMIC_MALLOC(requiredSize); if (NULL != newBuffer) { if (ptBuffers->errorMessageBuffer != NULL) { XMLVM_FREE(ptBuffers->errorMessageBuffer); } ptBuffers->errorMessageBuffer = newBuffer; ptBuffers->errorMessageBufferSize = requiredSize; } } /* Save the message */ if (ptBuffers->errorMessageBufferSize > 0) { sprintf(ptBuffers->errorMessageBuffer, "%s", errorMessage); ptBuffers->errorMessageBuffer[ptBuffers->errorMessageBufferSize - 1] = '\0'; } return portableCode; }