/* | |
------------------------------------------------------------------------------- | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
------------------------------------------------------------------------------- | |
------------------------------------------------------------------------------- | |
*/ | |
#if defined(_MSC_VER) | |
#include <stdio.h> | |
#include <eh.h> | |
#include <windows.h> | |
#include <winbase.h> | |
#endif | |
#include "uima/pragmas.hpp" //must be included first to disable warnings | |
#include "uima/msg.h" | |
#include <string> | |
#include <sstream> | |
#include "uima/macros.h" | |
#include "uima/trace.hpp" | |
#include "uima/strconvert.hpp" | |
#include "uima/unistrref.hpp" | |
#include "uima/comp_ids.h" | |
#include "uima/exceptions.hpp" | |
#include "uima/msgstrtab.h" | |
using namespace std; | |
namespace uima { | |
///Constructor with just the message id | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId | |
) : | |
iv_utMsgId(utMsgId) { | |
if ( iv_utMsgId == 0) { | |
iv_utMsgId = UIMA_MSG_ID_NO_MESSAGE_AVAILABLE; | |
} | |
} | |
///Constructor with a single char * parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const char * cpszParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
iv_vecParams.push_back((string)cpszParam1); | |
} | |
///Constructor with a single string parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const string & crstrParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
iv_vecParams.push_back(crstrParam1); | |
} | |
///Constructor with a single UChar * parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const UChar * cpuszParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
UnicodeStringRef(cpuszParam1).extract(s); // Convert to default encoding for platform | |
iv_vecParams.push_back(s); | |
} | |
///Constructor with a single UnicodeString parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const icu::UnicodeString & crustrParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
UnicodeStringRef(crustrParam1).extract(s); // Convert to default encoding for platform | |
iv_vecParams.push_back(s); | |
} | |
///Constructor with a single int parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
int iParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
iv_vecParams.push_back(long2String(iParam1, s)); | |
} | |
///Constructor with a single unsigned int parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
unsigned int uiParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
iv_vecParams.push_back(long2String((int) uiParam1, s)); | |
} | |
///Constructor with a single long parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
long lParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
iv_vecParams.push_back(long2String(lParam1, s)); | |
} | |
///Constructor with a single unsigned long parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
unsigned long ulParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
iv_vecParams.push_back(long2String((long) ulParam1, s)); | |
} | |
///Constructor with a single double parameter | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const double dParam1 | |
) : | |
iv_utMsgId(utMsgId) { | |
assert( iv_utMsgId != 0 ); | |
string s; | |
iv_vecParams.push_back(double2String(dParam1, s)); | |
} | |
///Constructor with a full parameter vector | |
ErrorMessage::ErrorMessage( | |
TyMessageId utMsgId, | |
const vector<string> & crvecParams | |
) : | |
iv_utMsgId(utMsgId), | |
iv_vecParams(crvecParams) { | |
assert( iv_utMsgId != 0 ); | |
} | |
/*------------------------------- Constructors -------------------------------*/ | |
ErrorContext::ErrorContext( | |
const ErrorMessage & crclMessage, | |
const char* pszFilename, | |
const char* pszFunction, | |
unsigned long ulLineNumber | |
): | |
iv_clMessage(crclMessage), | |
iv_pszFilename(pszFilename), | |
iv_pszFunction(pszFunction), | |
iv_ulLineNo(ulLineNumber) {} | |
#ifdef OS_STL | |
Exception::~Exception() | |
#else | |
Exception::~Exception() UIMA_THROW0() | |
#endif | |
{} | |
/*------------------------------ Output Support ------------------------------*/ | |
string | |
ErrorMessage::asString() const { | |
size_t numparams = getMessageParams().size(); | |
// Check for unknown message id | |
if (iv_utMsgId < 0 || iv_utMsgId > UIMA_MSG_ID_SIGNATURE_END) { | |
return string("Unknown message id " + iv_utMsgId); | |
} | |
//parameter substitution | |
//locate message in message table | |
const TCHAR ** messages = gs_aszMessageStringTable; | |
const TCHAR * msg = messages[iv_utMsgId]; | |
TCHAR * buf = new TCHAR[UIMA_MSG_MAX_STR_LEN]; | |
memset(buf,'\0',UIMA_MSG_MAX_STR_LEN); | |
int numwritten=0; | |
TCHAR * trg = buf; | |
while (*msg) { | |
if (numwritten > UIMA_MSG_MAX_STR_LEN) { | |
break; | |
} | |
if (*msg == UIMA_MSG_REPLACE_CHAR) { | |
msg = msg+1; | |
if (*msg == UIMA_MSG_REPLACE_CHAR) { | |
*trg = *msg; | |
trg = trg +1; | |
; | |
msg = msg+1; | |
numwritten++; | |
} else { //replace %n with the corresponding param | |
unsigned long index; | |
int len; | |
string arg; | |
// determine the number of the specified argument ... | |
index = (unsigned long) atol(msg); | |
if (index > numparams) // param not defined | |
{ | |
arg = "???"; // replace it by "dont-know" | |
} else { | |
// ... the indexed argument ... | |
arg = iv_vecParams[index - 1]; // zero-based array! | |
//assert(arg.length() > 0); | |
} | |
len = arg.length(); | |
// ... and then copy the argument | |
if (UIMA_MSG_MAX_STR_LEN-numwritten < len) { | |
len = UIMA_MSG_MAX_STR_LEN - numwritten; | |
} | |
if (len > 0) { | |
strncpy(trg, arg.c_str(), len); | |
trg = trg+len; | |
} | |
msg = msg+1; | |
while ( isdigit(*msg) ) { //handle arg number 10 or more | |
msg = msg+1; | |
} | |
} | |
} else { | |
*trg = *msg; | |
trg = trg+1; | |
msg = msg+1; | |
} | |
} | |
//cout << buf << endl; | |
string target(buf); | |
delete[] buf ; | |
return target; | |
//string target; | |
//target.assign(buf, UIMA_MSG_MAX_STR_LEN); // Copy the result to the string | |
//delete buf; | |
//return target; | |
} | |
ostream & | |
operator << ( | |
ostream & os, | |
const ErrorMessage & errorMsg | |
) { | |
os << errorMsg.asString(); | |
return(os); | |
} | |
string | |
ErrorContext::asString() const { | |
string s; | |
s += getMessage().asString(); | |
if (getFileName() != NULL) { | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " File : " + getFileName(); | |
} | |
if (getFunctionName() != NULL) { | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " Function : " + getFunctionName(); | |
} | |
if (getLineNumber() != 0) { | |
string sNum; | |
long2String(getLineNumber(), sNum); | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " Line : " + sNum; | |
} | |
return(s); | |
} | |
ostream & | |
operator << ( | |
ostream & os, | |
const ErrorContext & errContext | |
) { | |
os << errContext.asString(); | |
return (os); | |
} | |
void ErrorMessage::reset(void) { | |
iv_utMsgId = UIMA_MSG_ID_NO_MESSAGE_AVAILABLE; | |
iv_vecParams.clear(); | |
} | |
/* ----------------------------------------------------------------------- */ | |
/* ErrorInfo */ | |
/* ----------------------------------------------------------------------- */ | |
/*------------------------------- Statics -----------------------------------*/ | |
//initialize static member var to an initial value | |
const char * ErrorInfo::cv_cpszContextPrefix = " While : "; | |
const char * ErrorInfo::cv_cpszIndent = ""; | |
/*------------------------------- Constructors -------------------------------*/ | |
ErrorInfo::ErrorInfo( | |
const ErrorMessage & rclMessage, | |
TyErrorId ulErrorId, | |
ErrorInfo::EnSeverity enSeverity | |
) : | |
iv_clErrorMsg(rclMessage), | |
iv_ulErrorId(ulErrorId), | |
iv_enSeverity(enSeverity), | |
iv_vecContexts() {} | |
ErrorInfo::ErrorInfo( void ) : | |
iv_clErrorMsg(), | |
iv_ulErrorId(UIMA_ERR_NONE), | |
iv_enSeverity(recoverable), | |
iv_vecContexts() {} | |
ErrorInfo::~ErrorInfo() {} | |
//constructor (copy) | |
//? Exception::Exception( | |
//? const Exception& rclException | |
//? ) | |
//? { | |
//? } | |
/*---------------------------- Exception Context ----------------------------*/ | |
void | |
ErrorInfo::addContext( const ErrorContext & crclContext ) { | |
iv_vecContexts.push_back(crclContext); | |
} | |
const ErrorContext * | |
ErrorInfo::contextPtrAtIndex( size_t uiContextIndex ) const { | |
if (uiContextIndex >= iv_vecContexts.size()) { | |
return(NULL); | |
} | |
return(&iv_vecContexts[uiContextIndex]); | |
} | |
/*------------------------------ Output Support ------------------------------*/ | |
string | |
ErrorInfo::asString() const { | |
string s; | |
if (getErrorId() == UIMA_ERR_NONE) { | |
s += string("No Error\n"); | |
return (s); | |
} | |
if (getErrorId() != UIMA_ERR_NONE) { | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Error number : "; | |
string sErr; | |
long2String( getErrorId(), sErr); | |
s += sErr; | |
} | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Recoverable : " + (isRecoverable() ? "Yes" : "No"); | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Error : " + getMessage().asString(); | |
for (size_t i = 0; i < contextCount(); ++i) { | |
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + ErrorInfo::getGlobalErrorInfoContextPrefix(); | |
assert(EXISTS(contextPtrAtIndex(i))); //lint !e666: Expression with side effects passed to repeated parameter 1 in macro EXISTS | |
s += contextPtrAtIndex(i)->asString(); | |
} | |
s += string("\n"); | |
return (s); | |
} | |
///output support for streams | |
ostream & | |
operator << ( | |
ostream & os, | |
const ErrorInfo & errInfo | |
) { | |
os << errInfo.asString(); | |
return(os); | |
} | |
void ErrorInfo::reset(void) { | |
iv_clErrorMsg.reset(); | |
iv_ulErrorId = UIMA_ERR_NONE; | |
iv_enSeverity = recoverable; | |
iv_vecContexts.clear(); | |
} | |
/* ----------------------------------------------------------------------- */ | |
/* Exception */ | |
/* ----------------------------------------------------------------------- */ | |
Exception::Exception( | |
const ErrorMessage & rclMessage, | |
TyErrorId ulErrorId, | |
ErrorInfo::EnSeverity enSeverity | |
) : | |
EXCEPTION_BASE_CLASS(), | |
iv_clErrorInfo(rclMessage, ulErrorId, enSeverity) {} | |
Exception::Exception( | |
const ErrorInfo & crclErrorInfo | |
) : | |
EXCEPTION_BASE_CLASS(), | |
iv_clErrorInfo(crclErrorInfo) {} | |
/*------------------------------ Exception Type ------------------------------*/ | |
const char * Exception::getName() const { | |
return(_TEXT("unspecified exception")); | |
} | |
/*------------------------- Application Termination --------------------------*/ | |
void Exception::terminate() { | |
exit(iv_clErrorInfo.getErrorId()); //lint !e713: Loss of precision (arg. no. 1) (unsigned long to int) | |
} | |
/*------------------------------ Throw Support -------------------------------*/ | |
void Exception::assertParameter( | |
const char* /*exceptionText*/, | |
ErrorContext /*context*/ ) { | |
assert(false); | |
//not tested yet (and not used anywhere!) | |
} | |
/*------------------------- Logging Support ----------------------------------*/ | |
void Exception::logExceptionData() { | |
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_EXCEPTIONS); | |
clTrace.dump(_TEXT("Exception occured"), asString().c_str()); | |
//not implemented yet | |
} | |
/*------------------------------ Output Support ------------------------------*/ | |
string | |
Exception::asString() const { | |
//output the (class) name of the exception and its error info after it. | |
return string("\n") + | |
ErrorInfo::getGlobalErrorInfoIndent() + | |
"Exception : " + | |
getName() + | |
"\n" + | |
getErrorInfo().asString() + | |
"\n"; | |
} | |
ostream & | |
operator << ( | |
ostream & os, | |
const Exception & exception | |
) { | |
//output the (class) name of the exception and its error info after it. | |
os << exception.asString(); | |
return(os); | |
} | |
/*------------------------------ Static Method -------------------------------*/ | |
// Release contents of string container allocated by asString method | |
void | |
Exception::release(std::string & msg) { | |
msg.clear(); // Empty string | |
msg.reserve(1); // Reduce capacity so will use internal buffer & free external one | |
} | |
//private: | |
/*----------------------------- Hidden Functions -----------------------------*/ | |
Exception& Exception::operator=( const Exception& /*exc*/ ) { | |
assert(false); | |
return(*this); //lint !e527 unreachable | |
} //lint !e1745: member not assigned by private assignment operator | |
/* ----------------------------------------------------------------------- */ | |
/* Implementations of predefined exceptions */ | |
/* ----------------------------------------------------------------------- */ | |
/* | |
The following classes reimplement the ANSI standard exception hierarchy from | |
stdexcept.h as UIMACPP exceptions with context and message id support | |
*/ | |
UIMA_EXC_CLASSIMPLEMENT(Uima_logic_error ,Exception); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_runtime_error ,Exception); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_domain_error ,Uima_logic_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_invalid_argument ,Uima_logic_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_length_error ,Uima_logic_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_out_of_range ,Uima_logic_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_range_error ,Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_overflow_error ,Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(Uima_underflow_error ,Uima_runtime_error); | |
/** | |
The following exceptions are used by helper test classes that are no longer in the UIMACPP library: | |
CommandLineDriver DocBuffer ParseHandlers | |
*/ | |
UIMA_EXC_CLASSIMPLEMENT(ConsoleAbortExc ,Exception); | |
UIMA_EXC_CLASSIMPLEMENT(ParseHandlerExc ,Exception); | |
UIMA_EXC_CLASSIMPLEMENT(ExcDocBuffer ,Uima_out_of_range); | |
/** code page conversion errors */ | |
UIMA_EXC_CLASSIMPLEMENT(CodePageConversionException, uima::Exception); | |
/** | |
The following exception is used to report failures from APR functions | |
*/ | |
UIMA_EXC_CLASSIMPLEMENT(AprFailureException, Exception); | |
/* | |
The following classes provide a starting point for an exception hierarchy | |
*/ | |
//? UIMA_EXC_CLASSIMPLEMENT(ExcAssertionFailure, Exception); | |
UIMA_EXC_CLASSIMPLEMENT(ExcIllFormedInputError , Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(ExcInvalidParameter , Uima_invalid_argument); | |
UIMA_EXC_CLASSIMPLEMENT(ExcIndexOutOfRange , Uima_out_of_range); | |
//? UIMA_EXC_CLASSIMPLEMENT(ExcDeviceError ,Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(ExcInvalidRequest , Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(ExcResourceExhausted , Uima_runtime_error); | |
UIMA_EXC_CLASSIMPLEMENT(ExcOutOfMemory , ExcResourceExhausted); | |
//? UIMA_EXC_CLASSIMPLEMENT(ExcOutOfSystemResource, ResourceExhausted); | |
//? UIMA_EXC_CLASSIMPLEMENT(ExcOutOfWindowResource, ResourceExhausted); | |
UIMA_EXC_CLASSIMPLEMENT(ExcFileNotFoundError , Uima_runtime_error); | |
// Windows specific CException | |
ExcWinCException::ExcWinCException( | |
ErrorMessage clMessage, | |
TyErrorId ulErrorId, | |
ErrorInfo::EnSeverity enSeverity | |
) | |
: Uima_runtime_error (clMessage, ulErrorId, enSeverity) { | |
; | |
} | |
const char* | |
ExcWinCException :: getName() const { | |
return( "ExcWinCException" ); | |
} | |
ExcWinCException::~ExcWinCException () CHILD_DESTRUCT_THROW0() { | |
; | |
} | |
ExcWinCException::ExcWinCException (const ExcWinCException & a) : Uima_runtime_error (a) { | |
; | |
} | |
// Windows exceptions can be mapped only when compiled with MS VC++ | |
#if defined(_MSC_VER) | |
void translation_func( unsigned int u, _EXCEPTION_POINTERS* pExp ) { | |
const char * cpszMsg = NULL; | |
switch (u) { | |
case EXCEPTION_ACCESS_VIOLATION: | |
cpszMsg ="\"ACCESS VIOLATION\""; | |
break; | |
case EXCEPTION_DATATYPE_MISALIGNMENT: | |
cpszMsg ="\"DATATYPE MISALIGNMENT\""; | |
break; | |
case EXCEPTION_BREAKPOINT: | |
cpszMsg ="\"BREAKPOINT\""; | |
break; | |
case EXCEPTION_SINGLE_STEP: | |
cpszMsg ="\"SINGLE STEP\""; | |
break; | |
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: | |
cpszMsg ="\"ARRAY BOUNDS EXCEEDED\""; | |
break; | |
case EXCEPTION_FLT_DENORMAL_OPERAND: | |
cpszMsg ="\"FLT DENORMAL OPERAND\""; | |
break; | |
case EXCEPTION_FLT_DIVIDE_BY_ZERO: | |
cpszMsg ="\"FLT DIVIDE_BY ZERO\""; | |
break; | |
case EXCEPTION_FLT_INEXACT_RESULT: | |
cpszMsg ="\"FLT INEXACT_RESULT\""; | |
break; | |
case EXCEPTION_FLT_INVALID_OPERATION: | |
cpszMsg ="\"FLT INVALID OPERATION\""; | |
break; | |
case EXCEPTION_FLT_OVERFLOW: | |
cpszMsg ="\"FLT OVERFLOW\""; | |
break; | |
case EXCEPTION_FLT_STACK_CHECK: | |
cpszMsg ="\"FLT STACK_CHECK\""; | |
break; | |
case EXCEPTION_FLT_UNDERFLOW: | |
cpszMsg ="\"FLT UNDERFLOW\""; | |
break; | |
case EXCEPTION_INT_DIVIDE_BY_ZERO: | |
cpszMsg ="\"INT DIVIDE BY ZERO\""; | |
break; | |
case EXCEPTION_INT_OVERFLOW: | |
cpszMsg ="\"INT OVERFLOW\""; | |
break; | |
case EXCEPTION_PRIV_INSTRUCTION: | |
cpszMsg ="\"PRIV INSTRUCTION\""; | |
break; | |
case EXCEPTION_IN_PAGE_ERROR: | |
cpszMsg ="\"IN PAGE_ERROR\""; | |
break; | |
case EXCEPTION_ILLEGAL_INSTRUCTION: | |
cpszMsg ="\"ILLEGAL INSTRUCTION\""; | |
break; | |
case EXCEPTION_NONCONTINUABLE_EXCEPTION: | |
cpszMsg ="\"NONCONTINUABLE EXCEPTION\""; | |
break; | |
case EXCEPTION_STACK_OVERFLOW: | |
cpszMsg ="\"STACK OVERFLOW\""; | |
break; | |
case EXCEPTION_INVALID_DISPOSITION: | |
cpszMsg ="\"INVALID DISPOSITION\""; | |
break; | |
case EXCEPTION_GUARD_PAGE: | |
cpszMsg ="\"GUARD PAGE\""; | |
break; | |
case EXCEPTION_INVALID_HANDLE: | |
cpszMsg ="\"INVALID HANDLE\""; | |
break; | |
case CONTROL_C_EXIT: | |
cpszMsg ="\"CONTROL C EXIT\""; | |
break; | |
default: | |
cpszMsg = "Unknows Windows C Exception"; | |
break; | |
} | |
// throw our own type of exception so we know at least what was going on | |
// instead of just getting an unknown ... C++ excepition | |
throw ExcWinCException( ErrorMessage(UIMA_MSG_ID_EXC_WINDOWS_EXCEPTION, cpszMsg), | |
(TyErrorId)UIMA_ERR_ENGINE_WINDOWS_EXCEPTION, | |
ErrorInfo::unrecoverable); | |
} | |
#define UIMA_ENVVAR_DONT_MAP_WINDOWS_EXCEPTIONS "UIMA_DONT_MAP_WINDOWS_EXCEPTIONS" | |
// _set_se_translator should be called at the beginning of main | |
// since we have no access to main here, we declare a static var of a dummy | |
// type which does the _set_se_translator call in it's constructor | |
// Note: this only works if the compiler properly executes the ctors of | |
// such static vars in DLLs | |
class Dummy { | |
public: | |
Dummy( void ) { | |
if ( getenv(UIMA_ENVVAR_DONT_MAP_WINDOWS_EXCEPTIONS) == NULL) { | |
_set_se_translator( translation_func ); | |
} | |
} | |
}; | |
// static var of our dummy type | |
Dummy clDummy; | |
#endif | |
} |