1*a67afe4dSAndroid Build Coastguard Worker /*=== 2*a67afe4dSAndroid Build Coastguard Worker cexcept.h 2.0.1 (2008-Jul-19-Sat) 3*a67afe4dSAndroid Build Coastguard Worker http://www.nicemice.net/cexcept/ 4*a67afe4dSAndroid Build Coastguard Worker Adam M. Costello 5*a67afe4dSAndroid Build Coastguard Worker http://www.nicemice.net/amc/ 6*a67afe4dSAndroid Build Coastguard Worker 7*a67afe4dSAndroid Build Coastguard Worker An interface for exception-handling in ANSI C (C89 and subsequent ISO 8*a67afe4dSAndroid Build Coastguard Worker standards), developed jointly with Cosmin Truta. 9*a67afe4dSAndroid Build Coastguard Worker 10*a67afe4dSAndroid Build Coastguard Worker Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta. 11*a67afe4dSAndroid Build Coastguard Worker This software may be modified only if its author and version 12*a67afe4dSAndroid Build Coastguard Worker information is updated accurately, and may be redistributed 13*a67afe4dSAndroid Build Coastguard Worker only if accompanied by this unaltered notice. Subject to those 14*a67afe4dSAndroid Build Coastguard Worker restrictions, permission is granted to anyone to do anything 15*a67afe4dSAndroid Build Coastguard Worker with this software. The copyright holders make no guarantees 16*a67afe4dSAndroid Build Coastguard Worker regarding this software, and are not responsible for any damage 17*a67afe4dSAndroid Build Coastguard Worker resulting from its use. 18*a67afe4dSAndroid Build Coastguard Worker 19*a67afe4dSAndroid Build Coastguard Worker The cexcept interface is not compatible with and cannot interact 20*a67afe4dSAndroid Build Coastguard Worker with system exceptions (like division by zero or memory segmentation 21*a67afe4dSAndroid Build Coastguard Worker violation), compiler-generated exceptions (like C++ exceptions), or 22*a67afe4dSAndroid Build Coastguard Worker other exception-handling interfaces. 23*a67afe4dSAndroid Build Coastguard Worker 24*a67afe4dSAndroid Build Coastguard Worker When using this interface across multiple .c files, do not include 25*a67afe4dSAndroid Build Coastguard Worker this header file directly. Instead, create a wrapper header file that 26*a67afe4dSAndroid Build Coastguard Worker includes this header file and then invokes the define_exception_type 27*a67afe4dSAndroid Build Coastguard Worker macro (see below). The .c files should then include that header file. 28*a67afe4dSAndroid Build Coastguard Worker 29*a67afe4dSAndroid Build Coastguard Worker The interface consists of one type, one well-known name, and six macros. 30*a67afe4dSAndroid Build Coastguard Worker 31*a67afe4dSAndroid Build Coastguard Worker 32*a67afe4dSAndroid Build Coastguard Worker define_exception_type(type_name); 33*a67afe4dSAndroid Build Coastguard Worker 34*a67afe4dSAndroid Build Coastguard Worker This macro is used like an external declaration. It specifies 35*a67afe4dSAndroid Build Coastguard Worker the type of object that gets copied from the exception thrower to 36*a67afe4dSAndroid Build Coastguard Worker the exception catcher. The type_name can be any type that can be 37*a67afe4dSAndroid Build Coastguard Worker assigned to, that is, a non-constant arithmetic type, struct, union, 38*a67afe4dSAndroid Build Coastguard Worker or pointer. Examples: 39*a67afe4dSAndroid Build Coastguard Worker 40*a67afe4dSAndroid Build Coastguard Worker define_exception_type(int); 41*a67afe4dSAndroid Build Coastguard Worker 42*a67afe4dSAndroid Build Coastguard Worker enum exception { out_of_memory, bad_arguments, disk_full }; 43*a67afe4dSAndroid Build Coastguard Worker define_exception_type(enum exception); 44*a67afe4dSAndroid Build Coastguard Worker 45*a67afe4dSAndroid Build Coastguard Worker struct exception { int code; const char *msg; }; 46*a67afe4dSAndroid Build Coastguard Worker define_exception_type(struct exception); 47*a67afe4dSAndroid Build Coastguard Worker 48*a67afe4dSAndroid Build Coastguard Worker Because throwing an exception causes the object to be copied (not 49*a67afe4dSAndroid Build Coastguard Worker just once, but twice), programmers may wish to consider size when 50*a67afe4dSAndroid Build Coastguard Worker choosing the exception type. 51*a67afe4dSAndroid Build Coastguard Worker 52*a67afe4dSAndroid Build Coastguard Worker 53*a67afe4dSAndroid Build Coastguard Worker struct exception_context; 54*a67afe4dSAndroid Build Coastguard Worker 55*a67afe4dSAndroid Build Coastguard Worker This type may be used after the define_exception_type() macro has 56*a67afe4dSAndroid Build Coastguard Worker been invoked. A struct exception_context must be known to both 57*a67afe4dSAndroid Build Coastguard Worker the thrower and the catcher. It is expected that there be one 58*a67afe4dSAndroid Build Coastguard Worker context for each thread that uses exceptions. It would certainly 59*a67afe4dSAndroid Build Coastguard Worker be dangerous for multiple threads to access the same context. 60*a67afe4dSAndroid Build Coastguard Worker One thread can use multiple contexts, but that is likely to be 61*a67afe4dSAndroid Build Coastguard Worker confusing and not typically useful. The application can allocate 62*a67afe4dSAndroid Build Coastguard Worker this structure in any way it pleases--automatic, static, or dynamic. 63*a67afe4dSAndroid Build Coastguard Worker The application programmer should pretend not to know the structure 64*a67afe4dSAndroid Build Coastguard Worker members, which are subject to change. 65*a67afe4dSAndroid Build Coastguard Worker 66*a67afe4dSAndroid Build Coastguard Worker 67*a67afe4dSAndroid Build Coastguard Worker struct exception_context *the_exception_context; 68*a67afe4dSAndroid Build Coastguard Worker 69*a67afe4dSAndroid Build Coastguard Worker The Try/Catch and Throw statements (described below) implicitly 70*a67afe4dSAndroid Build Coastguard Worker refer to a context, using the name the_exception_context. It is 71*a67afe4dSAndroid Build Coastguard Worker the application's responsibility to make sure that this name yields 72*a67afe4dSAndroid Build Coastguard Worker the address of a mutable (non-constant) struct exception_context 73*a67afe4dSAndroid Build Coastguard Worker wherever those statements are used. Subject to that constraint, the 74*a67afe4dSAndroid Build Coastguard Worker application may declare a variable of this name anywhere it likes 75*a67afe4dSAndroid Build Coastguard Worker (inside a function, in a parameter list, or externally), and may 76*a67afe4dSAndroid Build Coastguard Worker use whatever storage class specifiers (static, extern, etc) or type 77*a67afe4dSAndroid Build Coastguard Worker qualifiers (const, volatile, etc) it likes. Examples: 78*a67afe4dSAndroid Build Coastguard Worker 79*a67afe4dSAndroid Build Coastguard Worker static struct exception_context 80*a67afe4dSAndroid Build Coastguard Worker * const the_exception_context = &foo; 81*a67afe4dSAndroid Build Coastguard Worker 82*a67afe4dSAndroid Build Coastguard Worker { struct exception_context *the_exception_context = bar; ... } 83*a67afe4dSAndroid Build Coastguard Worker 84*a67afe4dSAndroid Build Coastguard Worker int blah(struct exception_context *the_exception_context, ...); 85*a67afe4dSAndroid Build Coastguard Worker 86*a67afe4dSAndroid Build Coastguard Worker extern struct exception_context the_exception_context[1]; 87*a67afe4dSAndroid Build Coastguard Worker 88*a67afe4dSAndroid Build Coastguard Worker The last example illustrates a trick that avoids creating a pointer 89*a67afe4dSAndroid Build Coastguard Worker object separate from the structure object. 90*a67afe4dSAndroid Build Coastguard Worker 91*a67afe4dSAndroid Build Coastguard Worker The name could even be a macro, for example: 92*a67afe4dSAndroid Build Coastguard Worker 93*a67afe4dSAndroid Build Coastguard Worker struct exception_context ec_array[numthreads]; 94*a67afe4dSAndroid Build Coastguard Worker #define the_exception_context (ec_array + thread_id) 95*a67afe4dSAndroid Build Coastguard Worker 96*a67afe4dSAndroid Build Coastguard Worker Be aware that the_exception_context is used several times by the 97*a67afe4dSAndroid Build Coastguard Worker Try/Catch/Throw macros, so it shouldn't be expensive or have side 98*a67afe4dSAndroid Build Coastguard Worker effects. The expansion must be a drop-in replacement for an 99*a67afe4dSAndroid Build Coastguard Worker identifier, so it's safest to put parentheses around it. 100*a67afe4dSAndroid Build Coastguard Worker 101*a67afe4dSAndroid Build Coastguard Worker 102*a67afe4dSAndroid Build Coastguard Worker void init_exception_context(struct exception_context *ec); 103*a67afe4dSAndroid Build Coastguard Worker 104*a67afe4dSAndroid Build Coastguard Worker For context structures allocated statically (by an external 105*a67afe4dSAndroid Build Coastguard Worker definition or using the "static" keyword), the implicit 106*a67afe4dSAndroid Build Coastguard Worker initialization to all zeros is sufficient, but contexts allocated 107*a67afe4dSAndroid Build Coastguard Worker by other means must be initialized using this macro before they 108*a67afe4dSAndroid Build Coastguard Worker are used by a Try/Catch statement. It does no harm to initialize 109*a67afe4dSAndroid Build Coastguard Worker a context more than once (by using this macro on a statically 110*a67afe4dSAndroid Build Coastguard Worker allocated context, or using this macro twice on the same context), 111*a67afe4dSAndroid Build Coastguard Worker but a context must not be re-initialized after it has been used by a 112*a67afe4dSAndroid Build Coastguard Worker Try/Catch statement. 113*a67afe4dSAndroid Build Coastguard Worker 114*a67afe4dSAndroid Build Coastguard Worker 115*a67afe4dSAndroid Build Coastguard Worker Try statement 116*a67afe4dSAndroid Build Coastguard Worker Catch (expression) statement 117*a67afe4dSAndroid Build Coastguard Worker 118*a67afe4dSAndroid Build Coastguard Worker The Try/Catch/Throw macros are capitalized in order to avoid 119*a67afe4dSAndroid Build Coastguard Worker confusion with the C++ keywords, which have subtly different 120*a67afe4dSAndroid Build Coastguard Worker semantics. 121*a67afe4dSAndroid Build Coastguard Worker 122*a67afe4dSAndroid Build Coastguard Worker A Try/Catch statement has a syntax similar to an if/else statement, 123*a67afe4dSAndroid Build Coastguard Worker except that the parenthesized expression goes after the second 124*a67afe4dSAndroid Build Coastguard Worker keyword rather than the first. As with if/else, there are two 125*a67afe4dSAndroid Build Coastguard Worker clauses, each of which may be a simple statement ending with a 126*a67afe4dSAndroid Build Coastguard Worker semicolon or a brace-enclosed compound statement. But whereas 127*a67afe4dSAndroid Build Coastguard Worker the else clause is optional, the Catch clause is required. The 128*a67afe4dSAndroid Build Coastguard Worker expression must be a modifiable lvalue (something capable of being 129*a67afe4dSAndroid Build Coastguard Worker assigned to) of the same type (disregarding type qualifiers) that 130*a67afe4dSAndroid Build Coastguard Worker was passed to define_exception_type(). 131*a67afe4dSAndroid Build Coastguard Worker 132*a67afe4dSAndroid Build Coastguard Worker If a Throw that uses the same exception context as the Try/Catch is 133*a67afe4dSAndroid Build Coastguard Worker executed within the Try clause (typically within a function called 134*a67afe4dSAndroid Build Coastguard Worker by the Try clause), and the exception is not caught by a nested 135*a67afe4dSAndroid Build Coastguard Worker Try/Catch statement, then a copy of the exception will be assigned 136*a67afe4dSAndroid Build Coastguard Worker to the expression, and control will jump to the Catch clause. If no 137*a67afe4dSAndroid Build Coastguard Worker such Throw is executed, then the assignment is not performed, and 138*a67afe4dSAndroid Build Coastguard Worker the Catch clause is not executed. 139*a67afe4dSAndroid Build Coastguard Worker 140*a67afe4dSAndroid Build Coastguard Worker The expression is not evaluated unless and until the exception is 141*a67afe4dSAndroid Build Coastguard Worker caught, which is significant if it has side effects, for example: 142*a67afe4dSAndroid Build Coastguard Worker 143*a67afe4dSAndroid Build Coastguard Worker Try foo(); 144*a67afe4dSAndroid Build Coastguard Worker Catch (p[++i].e) { ... } 145*a67afe4dSAndroid Build Coastguard Worker 146*a67afe4dSAndroid Build Coastguard Worker IMPORTANT: Jumping into or out of a Try clause (for example via 147*a67afe4dSAndroid Build Coastguard Worker return, break, continue, goto, longjmp) is forbidden--the compiler 148*a67afe4dSAndroid Build Coastguard Worker will not complain, but bad things will happen at run-time. Jumping 149*a67afe4dSAndroid Build Coastguard Worker into or out of a Catch clause is okay, and so is jumping around 150*a67afe4dSAndroid Build Coastguard Worker inside a Try clause. In many cases where one is tempted to return 151*a67afe4dSAndroid Build Coastguard Worker from a Try clause, it will suffice to use Throw, and then return 152*a67afe4dSAndroid Build Coastguard Worker from the Catch clause. Another option is to set a flag variable and 153*a67afe4dSAndroid Build Coastguard Worker use goto to jump to the end of the Try clause, then check the flag 154*a67afe4dSAndroid Build Coastguard Worker after the Try/Catch statement. 155*a67afe4dSAndroid Build Coastguard Worker 156*a67afe4dSAndroid Build Coastguard Worker IMPORTANT: The values of any non-volatile automatic variables 157*a67afe4dSAndroid Build Coastguard Worker changed within the Try clause are undefined after an exception is 158*a67afe4dSAndroid Build Coastguard Worker caught. Therefore, variables modified inside the Try block whose 159*a67afe4dSAndroid Build Coastguard Worker values are needed later outside the Try block must either use static 160*a67afe4dSAndroid Build Coastguard Worker storage or be declared with the "volatile" type qualifier. 161*a67afe4dSAndroid Build Coastguard Worker 162*a67afe4dSAndroid Build Coastguard Worker 163*a67afe4dSAndroid Build Coastguard Worker Throw expression; 164*a67afe4dSAndroid Build Coastguard Worker 165*a67afe4dSAndroid Build Coastguard Worker A Throw statement is very much like a return statement, except that 166*a67afe4dSAndroid Build Coastguard Worker the expression is required. Whereas return jumps back to the place 167*a67afe4dSAndroid Build Coastguard Worker where the current function was called, Throw jumps back to the Catch 168*a67afe4dSAndroid Build Coastguard Worker clause of the innermost enclosing Try clause. The expression must 169*a67afe4dSAndroid Build Coastguard Worker be compatible with the type passed to define_exception_type(). The 170*a67afe4dSAndroid Build Coastguard Worker exception must be caught, otherwise the program may crash. 171*a67afe4dSAndroid Build Coastguard Worker 172*a67afe4dSAndroid Build Coastguard Worker Slight limitation: If the expression is a comma-expression, it must 173*a67afe4dSAndroid Build Coastguard Worker be enclosed in parentheses. 174*a67afe4dSAndroid Build Coastguard Worker 175*a67afe4dSAndroid Build Coastguard Worker 176*a67afe4dSAndroid Build Coastguard Worker Try statement 177*a67afe4dSAndroid Build Coastguard Worker Catch_anonymous statement 178*a67afe4dSAndroid Build Coastguard Worker 179*a67afe4dSAndroid Build Coastguard Worker When the value of the exception is not needed, a Try/Catch statement 180*a67afe4dSAndroid Build Coastguard Worker can use Catch_anonymous instead of Catch (expression). 181*a67afe4dSAndroid Build Coastguard Worker 182*a67afe4dSAndroid Build Coastguard Worker 183*a67afe4dSAndroid Build Coastguard Worker Everything below this point is for the benefit of the compiler. The 184*a67afe4dSAndroid Build Coastguard Worker application programmer should pretend not to know any of it, because it 185*a67afe4dSAndroid Build Coastguard Worker is subject to change. 186*a67afe4dSAndroid Build Coastguard Worker 187*a67afe4dSAndroid Build Coastguard Worker ===*/ 188*a67afe4dSAndroid Build Coastguard Worker 189*a67afe4dSAndroid Build Coastguard Worker 190*a67afe4dSAndroid Build Coastguard Worker #ifndef CEXCEPT_H 191*a67afe4dSAndroid Build Coastguard Worker #define CEXCEPT_H 192*a67afe4dSAndroid Build Coastguard Worker 193*a67afe4dSAndroid Build Coastguard Worker 194*a67afe4dSAndroid Build Coastguard Worker #include <setjmp.h> 195*a67afe4dSAndroid Build Coastguard Worker 196*a67afe4dSAndroid Build Coastguard Worker #define define_exception_type(etype) \ 197*a67afe4dSAndroid Build Coastguard Worker struct exception_context { \ 198*a67afe4dSAndroid Build Coastguard Worker jmp_buf *penv; \ 199*a67afe4dSAndroid Build Coastguard Worker int caught; \ 200*a67afe4dSAndroid Build Coastguard Worker volatile struct { etype etmp; } v; \ 201*a67afe4dSAndroid Build Coastguard Worker } 202*a67afe4dSAndroid Build Coastguard Worker 203*a67afe4dSAndroid Build Coastguard Worker /* etmp must be volatile because the application might use automatic */ 204*a67afe4dSAndroid Build Coastguard Worker /* storage for the_exception_context, and etmp is modified between */ 205*a67afe4dSAndroid Build Coastguard Worker /* the calls to setjmp() and longjmp(). A wrapper struct is used to */ 206*a67afe4dSAndroid Build Coastguard Worker /* avoid warnings about a duplicate volatile qualifier in case etype */ 207*a67afe4dSAndroid Build Coastguard Worker /* already includes it. */ 208*a67afe4dSAndroid Build Coastguard Worker 209*a67afe4dSAndroid Build Coastguard Worker #define init_exception_context(ec) ((void)((ec)->penv = 0)) 210*a67afe4dSAndroid Build Coastguard Worker 211*a67afe4dSAndroid Build Coastguard Worker #define Try \ 212*a67afe4dSAndroid Build Coastguard Worker { \ 213*a67afe4dSAndroid Build Coastguard Worker jmp_buf *exception__prev, exception__env; \ 214*a67afe4dSAndroid Build Coastguard Worker exception__prev = the_exception_context->penv; \ 215*a67afe4dSAndroid Build Coastguard Worker the_exception_context->penv = &exception__env; \ 216*a67afe4dSAndroid Build Coastguard Worker if (setjmp(exception__env) == 0) { \ 217*a67afe4dSAndroid Build Coastguard Worker do 218*a67afe4dSAndroid Build Coastguard Worker 219*a67afe4dSAndroid Build Coastguard Worker #define exception__catch(action) \ 220*a67afe4dSAndroid Build Coastguard Worker while (the_exception_context->caught = 0, \ 221*a67afe4dSAndroid Build Coastguard Worker the_exception_context->caught); \ 222*a67afe4dSAndroid Build Coastguard Worker } \ 223*a67afe4dSAndroid Build Coastguard Worker else { \ 224*a67afe4dSAndroid Build Coastguard Worker the_exception_context->caught = 1; \ 225*a67afe4dSAndroid Build Coastguard Worker } \ 226*a67afe4dSAndroid Build Coastguard Worker the_exception_context->penv = exception__prev; \ 227*a67afe4dSAndroid Build Coastguard Worker } \ 228*a67afe4dSAndroid Build Coastguard Worker if (!the_exception_context->caught || action) { } \ 229*a67afe4dSAndroid Build Coastguard Worker else 230*a67afe4dSAndroid Build Coastguard Worker 231*a67afe4dSAndroid Build Coastguard Worker #define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0)) 232*a67afe4dSAndroid Build Coastguard Worker #define Catch_anonymous exception__catch(0) 233*a67afe4dSAndroid Build Coastguard Worker 234*a67afe4dSAndroid Build Coastguard Worker /* Try ends with do, and Catch begins with while(0) and ends with */ 235*a67afe4dSAndroid Build Coastguard Worker /* else, to ensure that Try/Catch syntax is similar to if/else */ 236*a67afe4dSAndroid Build Coastguard Worker /* syntax. */ 237*a67afe4dSAndroid Build Coastguard Worker /* */ 238*a67afe4dSAndroid Build Coastguard Worker /* The 0 in while(0) is expressed as x=0,x in order to appease */ 239*a67afe4dSAndroid Build Coastguard Worker /* compilers that warn about constant expressions inside while(). */ 240*a67afe4dSAndroid Build Coastguard Worker /* Most compilers should still recognize that the condition is always */ 241*a67afe4dSAndroid Build Coastguard Worker /* false and avoid generating code for it. */ 242*a67afe4dSAndroid Build Coastguard Worker 243*a67afe4dSAndroid Build Coastguard Worker #define Throw \ 244*a67afe4dSAndroid Build Coastguard Worker for (;; longjmp(*the_exception_context->penv, 1)) \ 245*a67afe4dSAndroid Build Coastguard Worker the_exception_context->v.etmp = 246*a67afe4dSAndroid Build Coastguard Worker 247*a67afe4dSAndroid Build Coastguard Worker 248*a67afe4dSAndroid Build Coastguard Worker #endif /* CEXCEPT_H */ 249