| /* 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. |
| */ |
| |
| parcel Clownfish; |
| |
| __C__ |
| typedef void |
| (*CFISH_Err_Attempt_t)(void *context); |
| |
| #ifdef CFISH_USE_SHORT_NAMES |
| #define Err_Attempt_t CFISH_Err_Attempt_t |
| #endif |
| __END_C__ |
| |
| /** |
| * Exception. |
| * |
| * Clownfish::Err is the base class for exceptions in the Clownfish object |
| * hierarchy. |
| * |
| * The Err module also provides access to a per-thread Err shared variable via |
| * set_error() and get_error(). It may be used to store an Err object |
| * temporarily, so that calling code may choose how to handle a particular |
| * error condition. |
| */ |
| public class Clownfish::Err inherits Clownfish::Obj { |
| |
| String *mess; |
| |
| inert void |
| init_class(); |
| |
| inert incremented Err* |
| new(decremented String *mess); |
| |
| inert Err* |
| init(Err *self, decremented String *mess); |
| |
| /** Return a copy of the error message. |
| */ |
| public incremented String* |
| To_String(Err *self); |
| |
| /** Concatenate the supplied argument onto the error message. |
| */ |
| public void |
| Cat_Mess(Err *self, String *mess); |
| |
| /** Return the error message. |
| */ |
| public String* |
| Get_Mess(Err *self); |
| |
| /** Add information about the current stack frame onto the error message. |
| */ |
| void |
| Add_Frame(Err *self, const char *file, int line, const char *func); |
| |
| public void |
| Destroy(Err *self); |
| |
| /** Set the global error object, a per-thread Err shared variable. |
| */ |
| public inert void |
| set_error(decremented Err *error); |
| |
| /** Retrieve the global error object, a per-thread Err shared variable. |
| */ |
| public inert nullable Err* |
| get_error(); |
| |
| /** Run `routine` within the host's exception handling |
| * environment, catching and returning any errors that occur. |
| * |
| * If an unrecognized host exception is trapped, it will be wrapped in an |
| * Err so that it can be handled by Clownfish code. |
| * |
| * @return an Err, or NULL if no exception occurs. |
| */ |
| public inert incremented nullable Err* |
| trap(CFISH_Err_Attempt_t routine, void *context); |
| |
| /** Print an error message to stderr with some C contextual information. |
| * Usually invoked via the WARN(pattern, ...) macro. |
| */ |
| inert void |
| warn_at(const char *file, int line, const char *func, |
| const char *pattern, ...); |
| |
| /** Raise an exception. Usually invoked via the THROW macro. |
| */ |
| inert void |
| throw_at(Class *klass, const char *file, int line, const char *func, |
| const char *pattern, ...); |
| |
| /** Throw an existing exception after tacking on additional context data. |
| */ |
| inert void |
| rethrow(Err *error, const char *file, int line, const char *func); |
| |
| /** Raise an exception. Clean up the supplied message by decrementing its |
| * refcount. |
| * |
| * @param klass The Err class to throw. |
| * @param message Error message, to be output verbatim. |
| */ |
| inert void |
| throw_mess(Class *klass, decremented String *message); |
| |
| /** Invoke host exception handling. |
| */ |
| inert void |
| do_throw(decremented Err *self); |
| |
| /** Invoke host warning mechanism. Clean up the supplied message by |
| * decrementing its refcount. |
| * |
| * @param message Error message, to be output verbatim. |
| */ |
| inert void |
| warn_mess(decremented String *message); |
| |
| /** Create a formatted error message. Ususally invoked via the MAKE_MESS |
| * macro. |
| */ |
| inert String* |
| make_mess(const char *file, int line, const char *func, |
| const char *pattern, ...); |
| |
| /** Verify that `obj` is either NULL or inherits from |
| * `klass`. |
| * |
| * @return the object. |
| */ |
| inert nullable Obj* |
| downcast(Obj *obj, Class *klass, const char *file, int line, |
| const char *func); |
| |
| /** Verify that `obj` is not NULL and inherits from |
| * `klass`. |
| * |
| * @return the object. |
| */ |
| inert Obj* |
| certify(Obj *obj, Class *klass, const char *file, int line, |
| const char *func); |
| |
| /** Verify that an object belongs to a subclass and not an abstract class. |
| */ |
| inert inline void |
| abstract_class_check(Obj *obj, Class *klass); |
| |
| /** Throw an error after abstract method `method_name` was called on |
| * object `obj` of class `klass`. |
| */ |
| inert void |
| abstract_method_call(Obj *obj, Class *klass, const char *method_name); |
| |
| /** Throw an error after an invalid callback was called. |
| */ |
| inert void |
| invalid_callback(const char *method_name); |
| |
| /** On Windows, return a newly allocated buffer containing the string |
| * description for the the last error in the thread. |
| */ |
| inert char* |
| win_error(); |
| } |
| |
| __C__ |
| #ifdef CFISH_HAS_FUNC_MACRO |
| #define CFISH_ERR_FUNC_MACRO CFISH_FUNC_MACRO |
| #else |
| #define CFISH_ERR_FUNC_MACRO NULL |
| #endif |
| |
| #define CFISH_ERR_ADD_FRAME(_error) \ |
| CFISH_Err_Add_Frame(_error, __FILE__, __LINE__, \ |
| CFISH_ERR_FUNC_MACRO) |
| |
| #define CFISH_RETHROW(_error) \ |
| cfish_Err_rethrow((cfish_Err*)_error, __FILE__, __LINE__, \ |
| CFISH_ERR_FUNC_MACRO) |
| |
| /** Macro version of cfish_Err_throw_at which inserts contextual information |
| * automatically, provided that the compiler supports the necessary features. |
| */ |
| #ifdef CFISH_HAS_VARIADIC_MACROS |
| #ifdef CFISH_HAS_ISO_VARIADIC_MACROS |
| #define CFISH_THROW(_class, ...) \ |
| cfish_Err_throw_at(_class, __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \ |
| __VA_ARGS__) |
| #define CFISH_WARN(...) \ |
| cfish_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, __VA_ARGS__) |
| #define CFISH_MAKE_MESS(...) \ |
| cfish_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \ |
| __VA_ARGS__) |
| #elif defined(CFISH_HAS_GNUC_VARIADIC_MACROS) |
| #define CFISH_THROW(_class, args...) \ |
| cfish_Err_throw_at(_class, __FILE__, __LINE__, \ |
| CFISH_ERR_FUNC_MACRO, ##args) |
| #define CFISH_WARN(args...) \ |
| cfish_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args) |
| #define CFISH_MAKE_MESS(args...) \ |
| cfish_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args) |
| #endif |
| #else |
| void |
| CFISH_THROW(cfish_Class *klass, char* format, ...); |
| void |
| CFISH_WARN(char* format, ...); |
| cfish_String* |
| CFISH_MAKE_MESS(char* format, ...); |
| #endif |
| |
| #define CFISH_DOWNCAST(_obj, _class) \ |
| cfish_Err_downcast((cfish_Obj*)(_obj), (_class), \ |
| __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) |
| |
| |
| #define CFISH_CERTIFY(_obj, _class) \ |
| cfish_Err_certify((cfish_Obj*)(_obj), (_class), \ |
| __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO) |
| |
| static CFISH_INLINE void |
| cfish_Err_abstract_class_check(cfish_Obj *obj, cfish_Class *klass) { |
| cfish_Class *const my_class = (cfish_Class*)((cfish_Dummy*)obj)->klass; |
| if (my_class == klass) { |
| cfish_String *mess = CFISH_MAKE_MESS("%o is an abstract class", |
| cfish_Obj_get_class_name(obj)); |
| CFISH_DECREF_NN(obj); |
| cfish_Err_throw_mess(CFISH_ERR, mess); |
| } |
| } |
| |
| #define CFISH_ABSTRACT_CLASS_CHECK(_obj, _class) \ |
| cfish_Err_abstract_class_check(((cfish_Obj*)_obj), _class) |
| |
| #ifdef CFISH_USE_SHORT_NAMES |
| #define THROW CFISH_THROW |
| #define RETHROW CFISH_RETHROW |
| #define WARN CFISH_WARN |
| #define MAKE_MESS CFISH_MAKE_MESS |
| #define ERR_ADD_FRAME CFISH_ERR_ADD_FRAME |
| #define ERR_FUNC_MACRO CFISH_ERR_FUNC_MACRO |
| #define DOWNCAST CFISH_DOWNCAST |
| #define CERTIFY CFISH_CERTIFY |
| #define ABSTRACT_CLASS_CHECK CFISH_ABSTRACT_CLASS_CHECK |
| #endif |
| __END_C__ |
| |
| |