ExceptionSink.h
/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
ExceptionSink.h
Qore Programming Language ExceptionSink class definition
Copyright (C) 2003 - 2021 Qore Technologies, s.r.o.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Note that the Qore library is released under a choice of three open-source
licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
information.
*/
#ifndef _QORE_EXCEPTIONSINK_H
#define _QORE_EXCEPTIONSINK_H
#include <cstdarg>
#include <cstdio>
#include <string>
#include <vector>
// forward references
class QoreException;
class QoreXSinkException;
struct QoreProgramLocation;
struct QoreCallStack;
class ExceptionSink {
friend struct qore_es_private;
friend QoreXSinkException;
private:
struct qore_es_private* priv;
DLLLOCAL ExceptionSink(const ExceptionSink&);
DLLLOCAL ExceptionSink& operator=(const ExceptionSink&);
public:
DLLEXPORT ExceptionSink();
DLLEXPORT ~ExceptionSink();
DLLEXPORT void handleExceptions();
DLLEXPORT void handleWarnings();
DLLEXPORT bool isEvent() const;
DLLEXPORT bool isThreadExit() const;
DLLEXPORT bool isException() const;
DLLEXPORT operator bool () const;
DLLEXPORT AbstractQoreNode* raiseException(const char *err, const char *fmt, ...);
DLLEXPORT AbstractQoreNode* raiseErrnoException(const char *err, int en, const char *fmt, ...);
DLLEXPORT AbstractQoreNode* raiseErrnoException(const char *err, int en, QoreStringNode* desc);
DLLEXPORT AbstractQoreNode* raiseExceptionArg(const char* err, QoreValue arg, const char* fmt, ...);
DLLEXPORT AbstractQoreNode* raiseExceptionArg(const char* err, QoreValue arg, QoreStringNode* desc);
DLLEXPORT AbstractQoreNode* raiseExceptionArg(const char* err, QoreValue arg, QoreStringNode* desc, const QoreCallStack& stack);
DLLEXPORT AbstractQoreNode* raiseExceptionArg(const QoreProgramLocation& loc, const char* err, QoreValue arg, QoreStringNode* desc, const QoreCallStack& stack);
DLLEXPORT AbstractQoreNode* raiseExceptionArg(const QoreProgramLocation& loc, const char* err, QoreValue arg, QoreStringNode* desc);
DLLEXPORT AbstractQoreNode* raiseException(const char *err, QoreStringNode* desc);
DLLEXPORT AbstractQoreNode* raiseException(QoreStringNode *err, QoreStringNode* desc);
DLLEXPORT AbstractQoreNode* raiseException(QoreStringNode *err, QoreStringNode* desc, QoreValue arg);
DLLEXPORT void raiseException(const QoreProgramLocation& loc, const char* err, QoreValue arg, QoreValue desc);
DLLEXPORT void raiseException(const QoreProgramLocation& loc, const char* err, QoreValue arg, const char* fmt, ...);
DLLEXPORT void raiseThreadExit();
DLLEXPORT void assimilate(ExceptionSink *xs);
DLLEXPORT void assimilate(ExceptionSink &xs);
DLLEXPORT void outOfMemory();
DLLEXPORT void clear();
DLLEXPORT const QoreValue getExceptionErr();
DLLEXPORT const QoreValue getExceptionDesc();
DLLEXPORT const QoreValue getExceptionArg();
DLLEXPORT int appendLastDescription(const char* fmt, ...);
DLLLOCAL void raiseException(QoreException* e);
DLLLOCAL void raiseException(const QoreListNode* n);
DLLLOCAL QoreException* catchException();
DLLLOCAL QoreException* getException();
DLLLOCAL void overrideLocation(const QoreProgramLocation& loc);
DLLLOCAL void rethrow(QoreException* old);
DLLLOCAL static void defaultExceptionHandler(QoreException* e);
DLLLOCAL static void defaultWarningHandler(QoreException* e);
DLLLOCAL static void outputExceptionLocation(const char* fns, int start_line, int end_line, const char* srcs,
int offset, const char* langs, const char* types);
};
enum qore_call_t : signed char {
CT_UNUSED = -1,
CT_USER = 0,
CT_BUILTIN = 1,
CT_NEWTHREAD = 2,
CT_RETHROW = 3
};
struct QoreSourceLocation {
std::string label;
int start_line,
end_line;
std::string source;
unsigned offset = 0;
std::string code;
std::string lang;
DLLLOCAL QoreSourceLocation(const char* label, int start, int end, const char* code, const char* lang = "Qore") :
label(label), start_line(start), end_line(end), code(code), lang(lang) {
}
DLLLOCAL QoreSourceLocation(const char* label, int start, int end, const char* source, unsigned offset,
const char* code, const char* lang = "Qore") :
label(label), start_line(start), end_line(end), source(source), offset(offset), code(code), lang(lang) {
}
};
struct QoreCallStackElement : public QoreSourceLocation {
qore_call_t type;
DLLLOCAL QoreCallStackElement(qore_call_t type, const char* label, int start, int end, const char* code,
const char* lang = "Qore") :
QoreSourceLocation(label, start, end, code, lang), type(type) {
}
DLLLOCAL QoreCallStackElement(qore_call_t type, const char* label, int start, int end, const char* source,
unsigned offset, const char* code, const char* lang = "Qore") :
QoreSourceLocation(label, start, end, source, offset, code, lang), type(type) {
}
};
typedef std::vector<QoreCallStackElement> callstack_vec_t;
struct QoreCallStack : public callstack_vec_t {
DLLEXPORT void add(qore_call_t type, const char* label, int start, int end, const char* code,
const char* lang = "Qore");
DLLEXPORT void add(qore_call_t type, const char* label, int start, int end, const char* source,
unsigned offset, const char* code, const char* lang = "Qore");
};
static inline void alreadyDeleted(ExceptionSink *xsink, const char *cmeth) {
xsink->raiseException("OBJECT-ALREADY-DELETED", "the method %s() cannot be executed because the object has already been deleted", cmeth);
}
static inline void makeAccessDeletedObjectException(ExceptionSink *xsink, const char *mem, const char *cname) {
xsink->raiseException("OBJECT-ALREADY-DELETED", "attempt to access member '%s' of an already-deleted object of class '%s'", mem, cname);
}
static inline void makeAccessDeletedObjectException(ExceptionSink *xsink, const char *cname) {
xsink->raiseException("OBJECT-ALREADY-DELETED", "attempt to access an already-deleted object of class '%s'", cname);
}
class QoreExternalProgramLocationWrapper {
public:
DLLEXPORT QoreExternalProgramLocationWrapper();
DLLEXPORT QoreExternalProgramLocationWrapper(const QoreExternalProgramLocationWrapper&);
DLLEXPORT QoreExternalProgramLocationWrapper(QoreExternalProgramLocationWrapper&&);
DLLEXPORT QoreExternalProgramLocationWrapper(const char* file, int start_line, int end_line,
const char* source = nullptr, int offset = 0, const char* lang = nullptr);
DLLEXPORT ~QoreExternalProgramLocationWrapper();
DLLEXPORT void set(const char* file, int start_line, int end_line,
const char* source = nullptr, int offset = 0, const char* lang = nullptr);
DLLLOCAL const QoreProgramLocation& get() const {
return *loc;
}
DLLLOCAL const std::string& getFile() const {
return file_str;
}
DLLLOCAL const std::string& getSource() const {
return source_str;
}
DLLLOCAL const std::string& getLanguage() const {
return lang_str;
}
DLLEXPORT int getStartLine() const;
DLLEXPORT int getEndLine() const;
private:
// save strings for exceptions in case they are epheremal when this object is created
std::string file_str;
std::string source_str;
std::string lang_str;
// actual exception location
QoreProgramLocation* loc;
};
class QoreStackLocation {
public:
DLLLOCAL QoreStackLocation();
DLLLOCAL QoreStackLocation(const QoreStackLocation&) = default;
DLLLOCAL QoreStackLocation(QoreStackLocation&&) = default;
DLLLOCAL virtual ~QoreStackLocation() = default;
DLLLOCAL QoreStackLocation& operator=(const QoreStackLocation&) = default;
DLLLOCAL QoreStackLocation& operator=(QoreStackLocation&&) = default;
DLLLOCAL void setNext(const QoreStackLocation* next) {
stack_next = next;
}
DLLLOCAL virtual const QoreStackLocation* getNext() const {
return stack_next;
}
DLLLOCAL virtual QoreProgram* getProgram() const = 0;
DLLLOCAL virtual const AbstractStatement* getStatement() const = 0;
DLLLOCAL virtual const std::string& getCallName() const = 0;
DLLLOCAL virtual qore_call_t getCallType() const = 0;
DLLLOCAL virtual const QoreProgramLocation& getLocation() const = 0;
protected:
const QoreStackLocation* stack_next = nullptr;
};
class QoreExternalStackLocation : public QoreStackLocation {
friend class qore_external_runtime_stack_location_helper_priv;
public:
DLLEXPORT QoreExternalStackLocation();
DLLEXPORT QoreExternalStackLocation(const QoreExternalStackLocation&);
DLLEXPORT QoreExternalStackLocation(QoreExternalStackLocation&&);
DLLEXPORT virtual ~QoreExternalStackLocation();
DLLLOCAL QoreExternalStackLocation& operator=(const QoreExternalStackLocation&) = delete;
DLLLOCAL QoreExternalStackLocation& operator=(QoreExternalStackLocation&&) = delete;
DLLEXPORT virtual QoreProgram* getProgram() const;
DLLEXPORT virtual const AbstractStatement* getStatement() const;
private:
class qore_external_stack_location_priv* priv;
};
class QoreExternalRuntimeStackLocationHelper : public QoreExternalStackLocation {
public:
DLLEXPORT QoreExternalRuntimeStackLocationHelper();
DLLEXPORT QoreExternalRuntimeStackLocationHelper(const QoreExternalRuntimeStackLocationHelper&);
DLLEXPORT QoreExternalRuntimeStackLocationHelper(QoreExternalRuntimeStackLocationHelper&&);
DLLEXPORT ~QoreExternalRuntimeStackLocationHelper();
DLLLOCAL QoreExternalRuntimeStackLocationHelper& operator=(const QoreExternalRuntimeStackLocationHelper&) = delete;
DLLLOCAL QoreExternalRuntimeStackLocationHelper& operator=(QoreExternalRuntimeStackLocationHelper&&) = delete;
private:
class qore_external_runtime_stack_location_helper_priv* priv;
};
#endif
ExceptionSink::handleWarnings
DLLEXPORT void handleWarnings()
calls ExceptionSink::defaultWarningHandler() on all exceptions still present in the object and then d...
QoreSourceLocation::offset
unsigned offset
offset in source file (only used if source is not empty)
Definition: ExceptionSink.h:292
ExceptionSink::outOfMemory
DLLEXPORT void outOfMemory()
intended to be used to handle out of memory errors
ExceptionSink::getExceptionArg
DLLEXPORT const QoreValue getExceptionArg()
returns the argument of the top exception
QoreExternalStackLocation::operator=
DLLLOCAL QoreExternalStackLocation & operator=(const QoreExternalStackLocation &)=delete
no assignment operator
ExceptionSink::~ExceptionSink
DLLEXPORT ~ExceptionSink()
calls ExceptionSink::defaultExceptionHandler() on all exceptions still present in the object and then...
ExceptionSink::handleExceptions
DLLEXPORT void handleExceptions()
calls ExceptionSink::defaultExceptionHandler() on all exceptions still present in the object and then...
QoreExternalProgramLocationWrapper
returns a custom Qore program location for external modules to generate runtime exceptions with the s...
Definition: ExceptionSink.h:351
QoreStackLocation::getNext
virtual DLLLOCAL const QoreStackLocation * getNext() const
returns the next location in the stack or nullptr if there is none
Definition: ExceptionSink.h:445
QoreStackLocation::operator=
DLLLOCAL QoreStackLocation & operator=(const QoreStackLocation &)=default
default assignment operator
QoreStackLocation
Stack location element abstract class.
Definition: ExceptionSink.h:412
QoreSourceLocation::lang
std::string lang
the source language
Definition: ExceptionSink.h:294
ExceptionSink::raiseExceptionArg
DLLEXPORT AbstractQoreNode * raiseExceptionArg(const char *err, QoreValue arg, const char *fmt,...)
appends a Qore-language exception to the list, and sets the &#39;arg&#39; member (this object takes over the ...
QoreExternalStackLocation
Stack location element abstract class for external binary modules.
Definition: ExceptionSink.h:471
QoreExternalProgramLocationWrapper::getFile
DLLLOCAL const std::string & getFile() const
returns the file name
Definition: ExceptionSink.h:379
QoreStackLocation::getCallType
virtual DLLLOCAL qore_call_t getCallType() const =0
returns the call type
QoreXSinkException
class for C++ exception based on an ExceptionSink object
Definition: QoreXSinkException.h:51
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
QoreExternalRuntimeStackLocationHelper::operator=
DLLLOCAL QoreExternalRuntimeStackLocationHelper & operator=(const QoreExternalRuntimeStackLocationHelper &)=delete
no assignment operator
QoreExternalProgramLocationWrapper::getStartLine
DLLEXPORT int getStartLine() const
returns the start line
QoreExternalProgramLocationWrapper::getEndLine
DLLEXPORT int getEndLine() const
returns the start line
QoreSourceLocation::label
std::string label
the code label name (source file if source not present)
Definition: ExceptionSink.h:288
QoreStackLocation::~QoreStackLocation
virtual DLLLOCAL ~QoreStackLocation()=default
virtual destructor
ExceptionSink::raiseException
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
ExceptionSink::raiseErrnoException
DLLEXPORT AbstractQoreNode * raiseErrnoException(const char *err, int en, const char *fmt,...)
appends a Qore-language exception to the list and appends the result of strerror(errno) to the descri...
ExceptionSink::getExceptionErr
DLLEXPORT const QoreValue getExceptionErr()
returns the error of the top exception
ExceptionSink::appendLastDescription
DLLEXPORT int appendLastDescription(const char *fmt,...)
appends a formatted string to the top exception description if the desc value is a string ...
QoreStringNode
Qore&#39;s string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
QoreStackLocation::getCallName
virtual DLLLOCAL const std::string & getCallName() const =0
returns the name of the function or method call
QoreExternalProgramLocationWrapper::getSource
DLLLOCAL const std::string & getSource() const
returns the source
Definition: ExceptionSink.h:384
QoreStackLocation::getProgram
virtual DLLLOCAL QoreProgram * getProgram() const =0
returns the QoreProgram container
QoreExternalStackLocation::QoreExternalStackLocation
DLLEXPORT QoreExternalStackLocation()
create the object
QoreListNode
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
QoreSourceLocation::code
std::string code
the function or method call name; method calls in format class::name
Definition: ExceptionSink.h:293
QoreExternalStackLocation::~QoreExternalStackLocation
virtual DLLEXPORT ~QoreExternalStackLocation()
destroys the object
QoreExternalRuntimeStackLocationHelper::~QoreExternalRuntimeStackLocationHelper
DLLEXPORT ~QoreExternalRuntimeStackLocationHelper()
Restores the old runtime location.
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:267
QoreProgram
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreProgram.h:127
ExceptionSink::clear
DLLEXPORT void clear()
deletes the exception list immediately
QoreStackLocation::QoreStackLocation
DLLLOCAL QoreStackLocation()
constructor
QoreExternalProgramLocationWrapper::QoreExternalProgramLocationWrapper
DLLEXPORT QoreExternalProgramLocationWrapper()
empty constructor; use set() to set the location
QoreSourceLocation::start_line
int start_line
the start line
Definition: ExceptionSink.h:289
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
QoreExternalRuntimeStackLocationHelper
Sets the stack location for external modules providing language support.
Definition: ExceptionSink.h:505
QoreStackLocation::getLocation
virtual DLLLOCAL const QoreProgramLocation & getLocation() const =0
returns the source location of the element
QoreCallStackElement::type
qore_call_t type
the call stack element type
Definition: ExceptionSink.h:310
QoreCallStack::add
DLLEXPORT void add(qore_call_t type, const char *label, int start, int end, const char *code, const char *lang="Qore")
add an element to the end of the stack trace
QoreStackLocation::getStatement
virtual DLLLOCAL const AbstractStatement * getStatement() const =0
returns the statement for the call for internal Qore code
QoreSourceLocation::end_line
int end_line
the end line
Definition: ExceptionSink.h:289
QoreExternalStackLocation::getStatement
virtual DLLEXPORT const AbstractStatement * getStatement() const
returns the statement for the call for internal Qore code
ExceptionSink::isThreadExit
DLLEXPORT bool isThreadExit() const
returns true if thread_exit has been triggered
QoreExternalProgramLocationWrapper::getLanguage
DLLLOCAL const std::string & getLanguage() const
returns the language
Definition: ExceptionSink.h:389
ExceptionSink::raiseThreadExit
DLLEXPORT void raiseThreadExit()
sets the "thread_exit" flag; will cause the current thread to terminate
ExceptionSink::getExceptionDesc
DLLEXPORT const QoreValue getExceptionDesc()
returns the description of the top exception
ExceptionSink::ExceptionSink
DLLEXPORT ExceptionSink()
creates an empty ExceptionSink object
QoreSourceLocation
Qore source location; strings must be in the default encoding for the Qore process.
Definition: ExceptionSink.h:287
QoreExternalStackLocation::getProgram
virtual DLLEXPORT QoreProgram * getProgram() const
returns the QoreProgram container
QoreSourceLocation::source
std::string source
optional additional source file
Definition: ExceptionSink.h:291
QoreStackLocation::setNext
DLLLOCAL void setNext(const QoreStackLocation *next)
called when pushed on the stack to set the next location
Definition: ExceptionSink.h:440
QoreExternalRuntimeStackLocationHelper::QoreExternalRuntimeStackLocationHelper
DLLEXPORT QoreExternalRuntimeStackLocationHelper()
Sets the current runtime location.
ExceptionSink::isException
DLLEXPORT bool isException() const
returns true if at least one exception is present
QoreExternalProgramLocationWrapper::~QoreExternalProgramLocationWrapper
DLLEXPORT ~QoreExternalProgramLocationWrapper()
destructor; frees memory
QoreCallStack
Qore call stack.
Definition: ExceptionSink.h:328
ExceptionSink::assimilate
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
ExceptionSink::isEvent
DLLEXPORT bool isEvent() const
returns true if at least one exception is present or thread_exit has been triggered ...
QoreCallStackElement
call stack element; strings must be in the default encoding for the Qore process
Definition: ExceptionSink.h:309