140266059SGregory Neil Shapiro<html> 240266059SGregory Neil Shapiro<head> 340266059SGregory Neil Shapiro <title>libsm : Exception Handling</title> 440266059SGregory Neil Shapiro</head> 540266059SGregory Neil Shapiro<body> 640266059SGregory Neil Shapiro 740266059SGregory Neil Shapiro<a href="index.html">Back to libsm overview</a> 840266059SGregory Neil Shapiro 940266059SGregory Neil Shapiro<center> 1040266059SGregory Neil Shapiro <h1> libsm : Exception Handling </h1> 114313cc83SGregory Neil Shapiro <br> $Id: exc.html,v 1.13 2006-06-20 17:18:16 ca Exp $ 1240266059SGregory Neil Shapiro</center> 1340266059SGregory Neil Shapiro 1440266059SGregory Neil Shapiro<h2> Introduction </h2> 1540266059SGregory Neil Shapiro 1640266059SGregory Neil ShapiroThe exception handling package provides the facilities that 1740266059SGregory Neil Shapirofunctions in libsm use to report errors. 1840266059SGregory Neil ShapiroHere are the basic concepts: 1940266059SGregory Neil Shapiro 2040266059SGregory Neil Shapiro<ol> 2140266059SGregory Neil Shapiro<li> 2240266059SGregory Neil Shapiro When a function detects an exceptional condition at the library level, 2340266059SGregory Neil Shapiro it does not print an error message, or call syslog, or 2440266059SGregory Neil Shapiro exit the program. Instead, it reports the error back to its 2540266059SGregory Neil Shapiro caller, and lets the caller decide what to do. 2640266059SGregory Neil Shapiro This improves modularity, because error handling is separated 2740266059SGregory Neil Shapiro from error reporting. 2840266059SGregory Neil Shapiro <p> 2940266059SGregory Neil Shapiro<li> 3040266059SGregory Neil Shapiro Errors are not represented by a single integer error code, 31d0cef73dSGregory Neil Shapiro because then you can't represent everything that an error handler 3240266059SGregory Neil Shapiro might need to know about an error by a single integer. 3340266059SGregory Neil Shapiro Instead, errors are represented by exception objects. 3440266059SGregory Neil Shapiro An exception object contains an exception code and an array 3540266059SGregory Neil Shapiro of zero or more exception arguments. 3640266059SGregory Neil Shapiro The exception code is a string that specifies what kind of exception 3740266059SGregory Neil Shapiro this is, and the arguments may be integers, strings or exception objects. 3840266059SGregory Neil Shapiro <p> 3940266059SGregory Neil Shapiro<li> 4040266059SGregory Neil Shapiro Errors are not reported using a special return value, 4140266059SGregory Neil Shapiro because if you religiously check for error returns from every 4240266059SGregory Neil Shapiro function call that could fail, then most of your code ends up being 4340266059SGregory Neil Shapiro error handling code. Errors are reported by raising an exception. 4440266059SGregory Neil Shapiro When an exception is raised, we unwind the call stack 4540266059SGregory Neil Shapiro until we find an exception handler. If the exception is 4640266059SGregory Neil Shapiro not handled, then we print the exception on stderr and 4740266059SGregory Neil Shapiro exit the program. 4840266059SGregory Neil Shapiro</ol> 4940266059SGregory Neil Shapiro 5040266059SGregory Neil Shapiro<h2> Synopsis </h2> 5140266059SGregory Neil Shapiro 5240266059SGregory Neil Shapiro<pre> 5340266059SGregory Neil Shapiro#include <sm/exc.h> 5440266059SGregory Neil Shapiro 5540266059SGregory Neil Shapirotypedef struct sm_exc_type SM_EXC_TYPE_T; 5640266059SGregory Neil Shapirotypedef struct sm_exc SM_EXC_T; 5740266059SGregory Neil Shapirotypedef union sm_val SM_VAL_T; 5840266059SGregory Neil Shapiro 5940266059SGregory Neil Shapiro/* 6040266059SGregory Neil Shapiro** Exception types 6140266059SGregory Neil Shapiro*/ 6240266059SGregory Neil Shapiro 6340266059SGregory Neil Shapiroextern const char SmExcTypeMagic[]; 6440266059SGregory Neil Shapiro 6540266059SGregory Neil Shapirostruct sm_exc_type 6640266059SGregory Neil Shapiro{ 6740266059SGregory Neil Shapiro const char *sm_magic; 6840266059SGregory Neil Shapiro const char *etype_category; 6940266059SGregory Neil Shapiro const char *etype_argformat; 7040266059SGregory Neil Shapiro void (*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream); 7140266059SGregory Neil Shapiro const char *etype_printcontext; 7240266059SGregory Neil Shapiro}; 7340266059SGregory Neil Shapiro 7440266059SGregory Neil Shapiroextern const SM_EXC_TYPE_T SmEtypeOs; 7540266059SGregory Neil Shapiroextern const SM_EXC_TYPE_T SmEtypeErr; 7640266059SGregory Neil Shapiro 7740266059SGregory Neil Shapirovoid 7840266059SGregory Neil Shapirosm_etype_printf( 7940266059SGregory Neil Shapiro SM_EXC_T *exc, 8040266059SGregory Neil Shapiro SM_FILE_T *stream); 8140266059SGregory Neil Shapiro 8240266059SGregory Neil Shapiro/* 8340266059SGregory Neil Shapiro** Exception objects 8440266059SGregory Neil Shapiro*/ 8540266059SGregory Neil Shapiro 8640266059SGregory Neil Shapiroextern const char SmExcMagic[]; 8740266059SGregory Neil Shapiro 8840266059SGregory Neil Shapirounion sm_val 8940266059SGregory Neil Shapiro{ 9040266059SGregory Neil Shapiro int v_int; 9140266059SGregory Neil Shapiro long v_long; 9240266059SGregory Neil Shapiro char *v_str; 9340266059SGregory Neil Shapiro SM_EXC_T *v_exc; 9440266059SGregory Neil Shapiro}; 9540266059SGregory Neil Shapiro 9640266059SGregory Neil Shapirostruct sm_exc 9740266059SGregory Neil Shapiro{ 9840266059SGregory Neil Shapiro const char *sm_magic; 9940266059SGregory Neil Shapiro size_t exc_refcount; 10040266059SGregory Neil Shapiro const SM_EXC_TYPE_T *exc_type; 10140266059SGregory Neil Shapiro SM_VAL_T *exc_argv; 10240266059SGregory Neil Shapiro}; 10340266059SGregory Neil Shapiro 10440266059SGregory Neil ShapiroSM_EXC_T * 10540266059SGregory Neil Shapirosm_exc_new_x( 10640266059SGregory Neil Shapiro const SM_EXC_TYPE_T *type, 10740266059SGregory Neil Shapiro ...); 10840266059SGregory Neil Shapiro 10940266059SGregory Neil ShapiroSM_EXC_T * 11040266059SGregory Neil Shapirosm_exc_addref( 11140266059SGregory Neil Shapiro SM_EXC_T *exc); 11240266059SGregory Neil Shapiro 11340266059SGregory Neil Shapirovoid 11440266059SGregory Neil Shapirosm_exc_free( 11540266059SGregory Neil Shapiro SM_EXC_T *exc); 11640266059SGregory Neil Shapiro 11740266059SGregory Neil Shapirobool 11840266059SGregory Neil Shapirosm_exc_match( 11940266059SGregory Neil Shapiro SM_EXC_T *exc, 12040266059SGregory Neil Shapiro const char *pattern); 12140266059SGregory Neil Shapiro 12240266059SGregory Neil Shapirovoid 12340266059SGregory Neil Shapirosm_exc_print( 12440266059SGregory Neil Shapiro SM_EXC_T *exc, 12540266059SGregory Neil Shapiro SM_FILE_T *stream); 12640266059SGregory Neil Shapiro 12740266059SGregory Neil Shapirovoid 12840266059SGregory Neil Shapirosm_exc_write( 12940266059SGregory Neil Shapiro SM_EXC_T *exc, 13040266059SGregory Neil Shapiro SM_FILE_T *stream); 13140266059SGregory Neil Shapiro 13240266059SGregory Neil Shapirovoid 13340266059SGregory Neil Shapirosm_exc_raise_x( 13440266059SGregory Neil Shapiro SM_EXC_T *exc); 13540266059SGregory Neil Shapiro 13640266059SGregory Neil Shapirovoid 13740266059SGregory Neil Shapirosm_exc_raisenew_x( 13840266059SGregory Neil Shapiro const SM_EXC_TYPE_T *type, 13940266059SGregory Neil Shapiro ...); 14040266059SGregory Neil Shapiro 14140266059SGregory Neil Shapiro/* 14240266059SGregory Neil Shapiro** Ensure that cleanup code is executed, 14340266059SGregory Neil Shapiro** and/or handle an exception. 14440266059SGregory Neil Shapiro*/ 14540266059SGregory Neil ShapiroSM_TRY 14640266059SGregory Neil Shapiro Block of code that may raise an exception. 14740266059SGregory Neil ShapiroSM_FINALLY 14840266059SGregory Neil Shapiro Cleanup code that may raise an exception. 14940266059SGregory Neil Shapiro This clause is guaranteed to be executed even if an exception is 15040266059SGregory Neil Shapiro raised by the SM_TRY clause or by an earlier SM_FINALLY clause. 15140266059SGregory Neil Shapiro You may have 0 or more SM_FINALLY clauses. 15240266059SGregory Neil ShapiroSM_EXCEPT(exc, pattern) 15340266059SGregory Neil Shapiro Exception handling code, triggered by an exception 15440266059SGregory Neil Shapiro whose category matches 'pattern'. 15540266059SGregory Neil Shapiro You may have 0 or more SM_EXCEPT clauses. 15640266059SGregory Neil ShapiroSM_END_TRY 15740266059SGregory Neil Shapiro</pre> 15840266059SGregory Neil Shapiro 15940266059SGregory Neil Shapiro<h2> Overview </h2> 16040266059SGregory Neil Shapiro 16140266059SGregory Neil Shapiro An exception is an object which represents an exceptional condition, 16240266059SGregory Neil Shapiro which might be an error condition like "out of memory", or might be 16340266059SGregory Neil Shapiro a condition like "end of file". 16440266059SGregory Neil Shapiro<p> 16540266059SGregory Neil Shapiro Functions in libsm report errors and other unusual conditions by 16640266059SGregory Neil Shapiro raising an exception, rather than by returning an error code or 16740266059SGregory Neil Shapiro setting a global variable such as errno. If a libsm function is 16840266059SGregory Neil Shapiro capable of raising an exception, its name ends in "_x". 16940266059SGregory Neil Shapiro (We do not raise an exception when a bug is detected in the 17040266059SGregory Neil Shapiro program; instead, we terminate the program using <tt>sm_abort</tt>. 17140266059SGregory Neil Shapiro See <a href="assert.html">the assertion package</a> 17240266059SGregory Neil Shapiro for details.) 17340266059SGregory Neil Shapiro<p> 17440266059SGregory Neil Shapiro When you are using the libsm exception handling package, 17540266059SGregory Neil Shapiro you are using a new programming paradigm. 17640266059SGregory Neil Shapiro You will need to abandon some of the programming idioms 17740266059SGregory Neil Shapiro you are accustomed to, and switch to new idioms. 17840266059SGregory Neil Shapiro Here is an overview of some of these idioms. 17940266059SGregory Neil Shapiro<ol> 18040266059SGregory Neil Shapiro<li> 18140266059SGregory Neil Shapiro When a function is unable to complete its task because 18240266059SGregory Neil Shapiro of an exceptional condition, it reports this condition 18340266059SGregory Neil Shapiro by raising an exception. 18440266059SGregory Neil Shapiro <p> 18540266059SGregory Neil Shapiro Here is an example of how to construct an exception object 18640266059SGregory Neil Shapiro and raise an exception. 18740266059SGregory Neil Shapiro In this example, we convert a Unix system error into an exception. 18840266059SGregory Neil Shapiro<blockquote><pre> 18940266059SGregory Neil Shapirofd = open(path, O_RDONLY); 19040266059SGregory Neil Shapiroif (fd == -1) 19140266059SGregory Neil Shapiro sm_exc_raise_x(sm_exc_new_x(&SmEtypeOs, errno, "open", "%s", path)); 19240266059SGregory Neil Shapiro</pre></blockquote> 19340266059SGregory Neil Shapiro 19440266059SGregory Neil Shapiro Because the idiom <tt>sm_exc_raise_x(sm_exc_new_x(...))</tt> 19540266059SGregory Neil Shapiro is so common, it can be abbreviated as <tt>sm_exc_raisenew_x(...)</tt>. 19640266059SGregory Neil Shapiro<p> 19740266059SGregory Neil Shapiro<li> 19840266059SGregory Neil Shapiro When you detect an error at the application level, 19940266059SGregory Neil Shapiro you don't call a function like BSD's <tt>errx</tt>, 20040266059SGregory Neil Shapiro which prints an error message on stderr and exits the program. 20140266059SGregory Neil Shapiro Instead, you raise an exception. 20240266059SGregory Neil Shapiro This causes cleanup code in surrounding exception handlers 20340266059SGregory Neil Shapiro to be run before the program exits. 20440266059SGregory Neil Shapiro For example, instead of this: 20540266059SGregory Neil Shapiro<blockquote><pre> 20640266059SGregory Neil Shapiroerrx(1, "%s:%d: syntax error", filename, lineno); 20740266059SGregory Neil Shapiro</pre></blockquote> 20840266059SGregory Neil Shapiro 20940266059SGregory Neil Shapiro use this: 21040266059SGregory Neil Shapiro 21140266059SGregory Neil Shapiro<blockquote><pre> 21240266059SGregory Neil Shapirosm_exc_raisenew_x(&SmEtypeErr, "%s:%d: syntax error", filename, lineno); 21340266059SGregory Neil Shapiro</pre></blockquote> 21440266059SGregory Neil Shapiro 21540266059SGregory Neil Shapiro The latter code raises an exception, unwinding the call stack 21640266059SGregory Neil Shapiro and executing cleanup code. 21740266059SGregory Neil Shapiro If the exception is not handled, then the exception is printed 21840266059SGregory Neil Shapiro to stderr and the program exits. 21940266059SGregory Neil Shapiro The end result is substantially the same as a call to <tt>errx</tt>. 22040266059SGregory Neil Shapiro<p> 22140266059SGregory Neil Shapiro<li> 22240266059SGregory Neil Shapiro The SM_TRY ... SM_FINALLY ... control structure 22340266059SGregory Neil Shapiro ensures that cleanup code is executed and resources are released 22440266059SGregory Neil Shapiro in the presence of exceptions. 22540266059SGregory Neil Shapiro<p> 22640266059SGregory Neil Shapiro For example, suppose that you have written the following code: 22740266059SGregory Neil Shapiro 22840266059SGregory Neil Shapiro<blockquote><pre> 22940266059SGregory Neil Shapirorpool = sm_rpool_new_x(&SmRpoolRoot, 0); 23040266059SGregory Neil Shapiro... some code ... 23140266059SGregory Neil Shapirosm_rpool_free_x(rpool); 23240266059SGregory Neil Shapiro</pre></blockquote> 23340266059SGregory Neil Shapiro 23440266059SGregory Neil Shapiro If any of the functions called within "... some code ..." have 23540266059SGregory Neil Shapiro names ending in _x, then it is possible that an exception will be 23640266059SGregory Neil Shapiro raised, and if that happens, then "rpool" will not be freed. 23740266059SGregory Neil Shapiro And that's a bug. To fix this bug, change your code so it looks 23840266059SGregory Neil Shapiro like this: 23940266059SGregory Neil Shapiro 24040266059SGregory Neil Shapiro<blockquote><pre> 24140266059SGregory Neil Shapirorpool = sm_rpool_new_x(&SmRpoolRoot, 0); 24240266059SGregory Neil ShapiroSM_TRY 24340266059SGregory Neil Shapiro ... some code that can raise an exception ... 24440266059SGregory Neil ShapiroSM_FINALLY 24540266059SGregory Neil Shapiro sm_rpool_free_x(rpool); 24640266059SGregory Neil ShapiroSM_END_TRY 24740266059SGregory Neil Shapiro</pre></blockquote> 24840266059SGregory Neil Shapiro 24940266059SGregory Neil Shapiro<li> 25040266059SGregory Neil Shapiro The SM_TRY ... SM_EXCEPT ... control structure handles an exception. 25140266059SGregory Neil Shapiro Unhandled exceptions terminate the program. 25240266059SGregory Neil Shapiro For example, here is a simple exception handler 25340266059SGregory Neil Shapiro that traps all exceptions, and prints the exceptions: 25440266059SGregory Neil Shapiro 25540266059SGregory Neil Shapiro<blockquote><pre> 25640266059SGregory Neil ShapiroSM_TRY 25740266059SGregory Neil Shapiro /* code that can raise an exception */ 25840266059SGregory Neil Shapiro ... 25940266059SGregory Neil ShapiroSM_EXCEPT(exc, "*") 26040266059SGregory Neil Shapiro /* catch all exceptions */ 26140266059SGregory Neil Shapiro sm_exc_print(exc, stderr); 26240266059SGregory Neil ShapiroSM_END_TRY 26340266059SGregory Neil Shapiro</pre></blockquote> 26440266059SGregory Neil Shapiro 26540266059SGregory Neil Shapiro Exceptions are reference counted. The SM_END_TRY macro contains a 26640266059SGregory Neil Shapiro call to sm_exc_free, so you don't normally need to worry about freeing 26740266059SGregory Neil Shapiro an exception after handling it. In the rare case that you want an 26840266059SGregory Neil Shapiro exception to outlive an exception handler, then you increment its 26940266059SGregory Neil Shapiro reference count by calling sm_exc_addref. 27040266059SGregory Neil Shapiro<p> 27140266059SGregory Neil Shapiro<li> 27240266059SGregory Neil Shapiro The second argument of the SM_EXCEPT macro is a glob pattern 27340266059SGregory Neil Shapiro which specifies the types of exceptions that are to be handled. 27440266059SGregory Neil Shapiro For example, you might want to handle an end-of-file exception 27540266059SGregory Neil Shapiro differently from other exceptions. 27640266059SGregory Neil Shapiro Here's how you do that: 27740266059SGregory Neil Shapiro 27840266059SGregory Neil Shapiro<blockquote><pre> 27940266059SGregory Neil ShapiroSM_TRY 28040266059SGregory Neil Shapiro /* code that might raise end-of-file, or some other exception */ 28140266059SGregory Neil Shapiro ... 28240266059SGregory Neil ShapiroSM_EXCEPT(exc, "E:sm.eof") 28340266059SGregory Neil Shapiro /* what to do if end-of-file is encountered */ 28440266059SGregory Neil Shapiro ... 28540266059SGregory Neil ShapiroSM_EXCEPT(exc, "*") 28640266059SGregory Neil Shapiro /* what to do if some other exception is raised */ 28740266059SGregory Neil Shapiro ... 28840266059SGregory Neil ShapiroSM_END_TRY 28940266059SGregory Neil Shapiro</pre></blockquote> 29040266059SGregory Neil Shapiro</ol> 29140266059SGregory Neil Shapiro 29240266059SGregory Neil Shapiro<h2> Exception Values </h2> 29340266059SGregory Neil Shapiro 29440266059SGregory Neil ShapiroIn traditional C code, errors are usually denoted by a single integer, 29540266059SGregory Neil Shapirosuch as errno. In practice, errno does not carry enough information 29640266059SGregory Neil Shapiroto describe everything that an error handler might want to know about 29740266059SGregory Neil Shapiroan error. And the scheme is not very extensible: if several different 29840266059SGregory Neil Shapiropackages want to add additional error codes, it is hard to avoid 29940266059SGregory Neil Shapirocollisions. 30040266059SGregory Neil Shapiro 30140266059SGregory Neil Shapiro<p> 30240266059SGregory Neil ShapiroIn libsm, an exceptional condition is described 30340266059SGregory Neil Shapiroby an object of type SM_EXC_T. 30440266059SGregory Neil ShapiroAn exception object is created by specifying an exception type 30540266059SGregory Neil Shapiroand a list of exception arguments. 30640266059SGregory Neil Shapiro 30740266059SGregory Neil Shapiro<p> 30840266059SGregory Neil ShapiroThe exception arguments are an array of zero or more values. 30940266059SGregory Neil ShapiroThe values may be a mixture of ints, longs, strings, and exceptions. 31040266059SGregory Neil ShapiroIn the SM_EXC_T structure, the argument vector is represented 31140266059SGregory Neil Shapiroby <tt>SM_VAL_T *exc_argv</tt>, where <tt>SM_VAL_T</tt> 31240266059SGregory Neil Shapirois a union of the possible argument types. 31340266059SGregory Neil ShapiroThe number and types of exception arguments is determined by 31440266059SGregory Neil Shapirothe exception type. 31540266059SGregory Neil Shapiro 31640266059SGregory Neil Shapiro<p> 31740266059SGregory Neil ShapiroAn exception type is a statically initialized const object 31840266059SGregory Neil Shapiroof type SM_EXC_TYPE_T, which has the following members: 31940266059SGregory Neil Shapiro 32040266059SGregory Neil Shapiro<dl> 32140266059SGregory Neil Shapiro<dt> 32240266059SGregory Neil Shapiro<tt> const char *sm_magic </tt> 32340266059SGregory Neil Shapiro<dd> 32440266059SGregory Neil Shapiro A pointer to <tt>SmExcTypeMagic</tt>. 32540266059SGregory Neil Shapiro <p> 32640266059SGregory Neil Shapiro<dt> 32740266059SGregory Neil Shapiro<tt> const char *etype_category </tt> 32840266059SGregory Neil Shapiro<dd> 32940266059SGregory Neil Shapiro This is a string of the form 33040266059SGregory Neil Shapiro <tt>"</tt><i>class</i><tt>:</tt><i>name</i><tt>"</tt>. 33140266059SGregory Neil Shapiro <p> 33240266059SGregory Neil Shapiro The <i>class</i> is used to assign the exception type to 33340266059SGregory Neil Shapiro one of a number of broad categories of exceptions on which an 33440266059SGregory Neil Shapiro exception handler might want to discriminate. 33540266059SGregory Neil Shapiro I suspect that what we want is a hierarchical taxonomy, 33640266059SGregory Neil Shapiro but I don't have a full design for this yet. 33740266059SGregory Neil Shapiro For now, I am recommending the following classes: 33840266059SGregory Neil Shapiro <dl> 33940266059SGregory Neil Shapiro <dt><tt>"F"</tt> 34040266059SGregory Neil Shapiro <dd>A fatal error has occurred. 34140266059SGregory Neil Shapiro This is an error that prevents the application 34240266059SGregory Neil Shapiro from making any further progress, so the only 34340266059SGregory Neil Shapiro recourse is to raise an exception, execute cleanup code 34440266059SGregory Neil Shapiro as the stack is unwound, then exit the application. 34540266059SGregory Neil Shapiro The out-of-memory exception raised by sm_malloc_x 34640266059SGregory Neil Shapiro has category "F:sm.heap" because sendmail commits suicide 34740266059SGregory Neil Shapiro (after logging the error and cleaning up) when it runs out 34840266059SGregory Neil Shapiro of memory. 34940266059SGregory Neil Shapiro 35040266059SGregory Neil Shapiro <dt><tt>"E"</tt> 35140266059SGregory Neil Shapiro <dd>The function could not complete its task because an error occurred. 35240266059SGregory Neil Shapiro (It might be useful to define subclasses of this category, 353*d39bd2c1SGregory Neil Shapiro in which case our taxonomy becomes a tree, and 'F' becomes 35440266059SGregory Neil Shapiro a subclass of 'E'.) 35540266059SGregory Neil Shapiro 35640266059SGregory Neil Shapiro <dt><tt>"J"</tt> 35740266059SGregory Neil Shapiro <dd>This exception is being raised in order to effect a 35840266059SGregory Neil Shapiro non-local jump. No error has occurred; we are just 35940266059SGregory Neil Shapiro performing the non-local equivalent of a <tt>continue</tt>, 36040266059SGregory Neil Shapiro <tt>break</tt> or <tt>return</tt>. 36140266059SGregory Neil Shapiro 36240266059SGregory Neil Shapiro <dt><tt>"S"</tt> 36340266059SGregory Neil Shapiro <dd>The function was interrupted by a signal. 36440266059SGregory Neil Shapiro Signals are not errors because they occur asynchronously, 36540266059SGregory Neil Shapiro and they are semantically unrelated to the function that 36640266059SGregory Neil Shapiro happens to be executing when the signal arrives. 36740266059SGregory Neil Shapiro Note that it is extremely dangerous to raise an exception 36840266059SGregory Neil Shapiro from a signal handler. For example, if you are in the middle 36940266059SGregory Neil Shapiro of a call to malloc, you might corrupt the heap. 37040266059SGregory Neil Shapiro </dl> 37140266059SGregory Neil Shapiro Eric's libsm paper defines <tt>"W"</tt>, <tt>"D"</tt> and <tt>"I"</tt> 37240266059SGregory Neil Shapiro for Warning, Debug and Informational: 37340266059SGregory Neil Shapiro I suspect these categories only make sense in the context of 37440266059SGregory Neil Shapiro Eric's 1985 exception handling system which allowed you to 37540266059SGregory Neil Shapiro raise conditions without terminating the calling function. 37640266059SGregory Neil Shapiro <p> 37740266059SGregory Neil Shapiro The <i>name</i> uniquely identifies the exception type. 37840266059SGregory Neil Shapiro I recommend a string of the form 37940266059SGregory Neil Shapiro <i>library</i><tt>.</tt><i>package</i><tt>.</tt><i>detail</i>. 38040266059SGregory Neil Shapiro <p> 38140266059SGregory Neil Shapiro<dt> 38240266059SGregory Neil Shapiro<tt> const char *etype_argformat </tt> 38340266059SGregory Neil Shapiro<dd> 38440266059SGregory Neil Shapiro This is an array of single character codes. 38540266059SGregory Neil Shapiro Each code indicates the type of one of the exception arguments. 38640266059SGregory Neil Shapiro <tt>sm_exc_new_x</tt> uses this string to decode its variable 38740266059SGregory Neil Shapiro argument list into an exception argument vector. 38840266059SGregory Neil Shapiro The following type codes are supported: 38940266059SGregory Neil Shapiro <dl> 39040266059SGregory Neil Shapiro <dt><tt>i</tt> 39140266059SGregory Neil Shapiro <dd> 39240266059SGregory Neil Shapiro The exception argument has type <tt>int</tt>. 39340266059SGregory Neil Shapiro <dt><tt>l</tt> 39440266059SGregory Neil Shapiro <dd> 39540266059SGregory Neil Shapiro The exception argument has type <tt>long</tt>. 39640266059SGregory Neil Shapiro <dt><tt>e</tt> 39740266059SGregory Neil Shapiro <dd> 39840266059SGregory Neil Shapiro The exception argument has type <tt>SM_EXC_T*</tt>. 39940266059SGregory Neil Shapiro The value may either be <tt>NULL</tt> or a pointer 40040266059SGregory Neil Shapiro to an exception. The pointer value is simply copied 40140266059SGregory Neil Shapiro into the exception argument vector. 40240266059SGregory Neil Shapiro <dt><tt>s</tt> 40340266059SGregory Neil Shapiro <dd> 40440266059SGregory Neil Shapiro The exception argument has type <tt>char*</tt>. 40540266059SGregory Neil Shapiro The value may either be <tt>NULL</tt> or a pointer 40640266059SGregory Neil Shapiro to a character string. In the latter case, 40740266059SGregory Neil Shapiro <tt>sm_exc_new_x</tt> will make a copy of the string. 40840266059SGregory Neil Shapiro <dt><tt>r</tt> 40940266059SGregory Neil Shapiro <dd> 41040266059SGregory Neil Shapiro The exception argument has type <tt>char*</tt>. 41140266059SGregory Neil Shapiro <tt>sm_exc_new_x</tt> will read a printf-style 41240266059SGregory Neil Shapiro format string argument followed by a list of printf 41340266059SGregory Neil Shapiro arguments from its variable argument list, and convert 41440266059SGregory Neil Shapiro these into a string. 41540266059SGregory Neil Shapiro This type code can only occur as the last element 41640266059SGregory Neil Shapiro of <tt>exc_argformat</tt>. 41740266059SGregory Neil Shapiro </dl> 41840266059SGregory Neil Shapiro <p> 41940266059SGregory Neil Shapiro<dt> 42040266059SGregory Neil Shapiro<tt> void (*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream) </tt> 42140266059SGregory Neil Shapiro<dd> 42240266059SGregory Neil Shapiro This function prints an exception of the specified type 42340266059SGregory Neil Shapiro onto an output stream. 42440266059SGregory Neil Shapiro The final character printed is not a newline. 42540266059SGregory Neil Shapiro</dl> 42640266059SGregory Neil Shapiro 42740266059SGregory Neil Shapiro<h2> Standard Exceptions and Exception Types </h2> 42840266059SGregory Neil Shapiro 42940266059SGregory Neil ShapiroLibsm defines one standard exception value, <tt>SmHeapOutOfMemory</tt>. 43040266059SGregory Neil ShapiroThis is a statically initialized const variable, because it seems 43140266059SGregory Neil Shapirolike a bad idea to dynamically allocate an exception object to 43240266059SGregory Neil Shapiroreport a low memory condition. 43340266059SGregory Neil ShapiroThis exception has category <tt>"F:sm.heap"</tt>. 43440266059SGregory Neil ShapiroIf you need to, you can explicitly raise this exception 43540266059SGregory Neil Shapirowith <tt>sm_exc_raise_x(&SmHeapOutOfMemory)</tt>. 43640266059SGregory Neil Shapiro 43740266059SGregory Neil Shapiro<p> 43840266059SGregory Neil ShapiroStatically initialized exception values cannot contain any 43940266059SGregory Neil Shapirorun-time parameters, so the normal case is to dynamically allocate 44040266059SGregory Neil Shapiroa new exception object whenever you raise an exception. 44140266059SGregory Neil ShapiroBefore you can create an exception, you need an exception type. 44240266059SGregory Neil ShapiroLibsm defines the following standard exception types. 44340266059SGregory Neil Shapiro 44440266059SGregory Neil Shapiro<dl> 44540266059SGregory Neil Shapiro<dt> 44640266059SGregory Neil Shapiro<tt> SmEtypeOs </tt> 44740266059SGregory Neil Shapiro<dd> 44840266059SGregory Neil Shapiro This represents a generic operating system error. 44940266059SGregory Neil Shapiro The category is <tt>"E:sm.os"</tt>. 45040266059SGregory Neil Shapiro The argformat is <tt>"isr"</tt>, 45140266059SGregory Neil Shapiro where argv[0] is the value of <tt>errno</tt> 45240266059SGregory Neil Shapiro after a system call has failed, 45340266059SGregory Neil Shapiro argv[1] is the name of the function (usually a system call) that failed, 45440266059SGregory Neil Shapiro and argv[2] is either <tt>NULL</tt> 45540266059SGregory Neil Shapiro or a character string which describes some of the arguments 45640266059SGregory Neil Shapiro to the failing system call (usually it is just a file name). 45740266059SGregory Neil Shapiro Here's an example of raising an exception: 45840266059SGregory Neil Shapiro 45940266059SGregory Neil Shapiro<blockquote><pre> 46040266059SGregory Neil Shapirofd = open(filename, O_RDONLY); 46140266059SGregory Neil Shapiroif (fd == -1) 46240266059SGregory Neil Shapiro sm_exc_raisenew_x(&SmEtypeOs, errno, "open", "%s", filename); 46340266059SGregory Neil Shapiro</pre></blockquote> 46440266059SGregory Neil Shapiro 46540266059SGregory Neil Shapiro If errno is ENOENT and filename is "/etc/mail/snedmail.cf", 46640266059SGregory Neil Shapiro then the exception raised by the above code will be printed as 46740266059SGregory Neil Shapiro 46840266059SGregory Neil Shapiro<blockquote><pre> 46940266059SGregory Neil Shapiro/etc/mail/snedmail.cf: open failed: No such file or directory 47040266059SGregory Neil Shapiro</pre></blockquote> 47140266059SGregory Neil Shapiro 47240266059SGregory Neil Shapiro<dt> 47340266059SGregory Neil Shapiro<tt> SmEtypeErr </tt> 47440266059SGregory Neil Shapiro<dd> 47540266059SGregory Neil Shapiro This represents a generic error. 47640266059SGregory Neil Shapiro The category is <tt>"E:sm.err"</tt>, 47740266059SGregory Neil Shapiro and the argformat is <tt>"r"</tt>. 47840266059SGregory Neil Shapiro You can use it 47940266059SGregory Neil Shapiro in application contexts where you are raising an exception 48040266059SGregory Neil Shapiro for the purpose of terminating the program. 48140266059SGregory Neil Shapiro You know the exception won't be handled, 48240266059SGregory Neil Shapiro so you don't need to worry about packaging the error for 48340266059SGregory Neil Shapiro later analysis by an exception handler. 48440266059SGregory Neil Shapiro All you need to specify is the message string that 48540266059SGregory Neil Shapiro will be printed to stderr before the program exits. 48640266059SGregory Neil Shapiro For example, 48740266059SGregory Neil Shapiro 48840266059SGregory Neil Shapiro<blockquote><pre> 48940266059SGregory Neil Shapirosm_exc_raisenew_x(&SmEtypeErr, "name lookup failed: %s", name); 49040266059SGregory Neil Shapiro</pre></blockquote> 49140266059SGregory Neil Shapiro</dl> 49240266059SGregory Neil Shapiro 49340266059SGregory Neil Shapiro<h2> Custom Exception Types </h2> 49440266059SGregory Neil Shapiro 49540266059SGregory Neil ShapiroIf you are writing a library package, and you need to raise 49640266059SGregory Neil Shapiroexceptions that are not standard Unix system errors, 49740266059SGregory Neil Shapirothen you need to define one or more new exception types. 49840266059SGregory Neil Shapiro 49940266059SGregory Neil Shapiro<p> 50040266059SGregory Neil ShapiroEvery new exception type needs a print function. 50140266059SGregory Neil ShapiroThe standard print function <tt>sm_etype_printf</tt> 50240266059SGregory Neil Shapirois all you need in the majority of cases. 50340266059SGregory Neil ShapiroIt prints the <tt>etype_printcontext</tt> string of the exception type, 50440266059SGregory Neil Shapirosubstituting occurrences of %0 through %9 with the corresponding 50540266059SGregory Neil Shapiroexception argument. 50640266059SGregory Neil ShapiroIf exception argument 3 is an int or long, 50740266059SGregory Neil Shapirothen %3 will print the argument in decimal, 50840266059SGregory Neil Shapiroand %o3 or %x3 will print it in octal or hex. 50940266059SGregory Neil Shapiro 51040266059SGregory Neil Shapiro<p> 51140266059SGregory Neil ShapiroIn the following example, I will assume that your library 51240266059SGregory Neil Shapiropackage implements regular expressions, and can raise 5 different exceptions. 51340266059SGregory Neil ShapiroWhen compiling a regular expression, 3 different syntax errors 51440266059SGregory Neil Shapirocan be reported: 51540266059SGregory Neil Shapiro<ul> 51640266059SGregory Neil Shapiro<li>unbalanced parenthesis 51740266059SGregory Neil Shapiro<li>unbalanced bracket 51840266059SGregory Neil Shapiro<li>missing argument for repetition operator 51940266059SGregory Neil Shapiro</ul> 52040266059SGregory Neil ShapiroWhenever one of these errors is reported, you will also report 52140266059SGregory Neil Shapirothe index of the character within the regex string at which the 52240266059SGregory Neil Shapirosyntax error was detected. 52340266059SGregory Neil ShapiroThe fourth exception is raised if a compiled regular expression 52440266059SGregory Neil Shapirois invalid: this exception has no arguments. 52540266059SGregory Neil ShapiroThe fifth exception is raised if the package runs out of memory: 52640266059SGregory Neil Shapirofor this, you use the standard <tt>SmHeapOutOfMemory</tt> exception. 52740266059SGregory Neil Shapiro 52840266059SGregory Neil Shapiro<p> 52940266059SGregory Neil ShapiroThe obvious approach is to define 4 separate exception types. 53040266059SGregory Neil ShapiroHere they are: 53140266059SGregory Neil Shapiro 53240266059SGregory Neil Shapiro<blockquote><pre> 53340266059SGregory Neil Shapiro/* print a regular expression syntax error */ 53440266059SGregory Neil Shapirovoid 53540266059SGregory Neil Shapirorx_esyntax_print(SM_EXC_T *exc, SM_FILE_T *stream) 53640266059SGregory Neil Shapiro{ 53740266059SGregory Neil Shapiro sm_io_fprintf(stream, "rx syntax error at character %d: %s", 53840266059SGregory Neil Shapiro exc->exc_argv[0].v_int, 53940266059SGregory Neil Shapiro exc->exc_type->etype_printcontext); 54040266059SGregory Neil Shapiro} 54140266059SGregory Neil ShapiroSM_EXC_TYPE_T RxSyntaxParen = { 54240266059SGregory Neil Shapiro SmExcTypeMagic, 54340266059SGregory Neil Shapiro "E:mylib.rx.syntax.paren", 54440266059SGregory Neil Shapiro "i", 54540266059SGregory Neil Shapiro rx_esyntax_print, 54640266059SGregory Neil Shapiro "unbalanced parenthesis" 54740266059SGregory Neil Shapiro}; 54840266059SGregory Neil ShapiroSM_EXC_TYPE_T RxSyntaxBracket = { 54940266059SGregory Neil Shapiro SmExcTypeMagic, 55040266059SGregory Neil Shapiro "E:mylib.rx.syntax.bracket", 55140266059SGregory Neil Shapiro "i", 55240266059SGregory Neil Shapiro rx_esyntax_print, 55340266059SGregory Neil Shapiro "unbalanced bracket" 55440266059SGregory Neil Shapiro}; 55540266059SGregory Neil ShapiroSM_EXC_TYPE_T RxSyntaxMissingArg = { 55640266059SGregory Neil Shapiro SmExcTypeMagic, 55740266059SGregory Neil Shapiro "E:mylib.rx.syntax.missingarg", 55840266059SGregory Neil Shapiro "i", 55940266059SGregory Neil Shapiro rx_esyntax_print, 56040266059SGregory Neil Shapiro "missing argument for repetition operator" 56140266059SGregory Neil Shapiro}; 56240266059SGregory Neil Shapiro 56340266059SGregory Neil ShapiroSM_EXC_TYPE_T RxRunCorrupt = { 56440266059SGregory Neil Shapiro SmExcTypeMagic, 56540266059SGregory Neil Shapiro "E:mylib.rx.run.corrupt", 56640266059SGregory Neil Shapiro "", 56740266059SGregory Neil Shapiro sm_etype_printf, 56840266059SGregory Neil Shapiro "rx runtime error: compiled regular expression is corrupt" 56940266059SGregory Neil Shapiro}; 57040266059SGregory Neil Shapiro</pre></blockquote> 57140266059SGregory Neil Shapiro 57240266059SGregory Neil Shapiro<p> 57340266059SGregory Neil ShapiroWith the above definitions, you can raise a syntax error reporting 57440266059SGregory Neil Shapiroan unbalanced parenthesis at string offset <tt>i</tt> using: 57540266059SGregory Neil Shapiro<blockquote><pre> 57640266059SGregory Neil Shapirosm_exc_raisenew_x(&RxSyntaxParen, i); 57740266059SGregory Neil Shapiro</pre></blockquote> 57840266059SGregory Neil Shapiro 57940266059SGregory Neil ShapiroIf <tt>i==42</tt> then this exception will be printed as: 58040266059SGregory Neil Shapiro<blockquote><pre> 58140266059SGregory Neil Shapirorx syntax error at character 42: unbalanced parenthesis 58240266059SGregory Neil Shapiro</pre></blockquote> 58340266059SGregory Neil Shapiro 58440266059SGregory Neil ShapiroAn exception handler can provide special handling for regular 58540266059SGregory Neil Shapiroexpression syntax errors using this code: 58640266059SGregory Neil Shapiro<blockquote><pre> 58740266059SGregory Neil ShapiroSM_TRY 58840266059SGregory Neil Shapiro ... code that might raise an exception ... 58940266059SGregory Neil ShapiroSM_EXCEPT(exc, "E:mylib.rx.syntax.*") 59040266059SGregory Neil Shapiro int i = exc->exc_argv[0].v_int; 59140266059SGregory Neil Shapiro ... handle a regular expression syntax error ... 59240266059SGregory Neil ShapiroSM_END_TRY 59340266059SGregory Neil Shapiro</pre></blockquote> 59440266059SGregory Neil Shapiro 59540266059SGregory Neil Shapiro<p> 59640266059SGregory Neil ShapiroExternal requirements may force you to define an integer code 59740266059SGregory Neil Shapirofor each error reported by your package. Or you may be wrapping 59840266059SGregory Neil Shapiroan existing package that works this way. In this case, it might 59940266059SGregory Neil Shapiromake sense to define a single exception type, patterned after SmEtypeOs, 60040266059SGregory Neil Shapiroand include the integer code as an exception argument. 60140266059SGregory Neil Shapiro 60240266059SGregory Neil Shapiro<p> 60340266059SGregory Neil ShapiroYour package might intercept an exception E generated by a lower 60440266059SGregory Neil Shapirolevel package, and then reclassify it as a different expression E'. 60540266059SGregory Neil ShapiroFor example, a package for reading a configuration file might 60640266059SGregory Neil Shapiroreclassify one of the regular expression syntax errors from the 60740266059SGregory Neil Shapiroprevious example as a configuration file syntax error. 60840266059SGregory Neil ShapiroWhen you do this, the new exception E' should include the original 60940266059SGregory Neil Shapiroexception E as an exception parameter, and the print function for 61040266059SGregory Neil Shapiroexception E' should print the high level description of the exception 61140266059SGregory Neil Shapiro(eg, "syntax error in configuration file %s at line %d\n"), 61240266059SGregory Neil Shapirothen print the subexception that is stored as an exception parameter. 61340266059SGregory Neil Shapiro 61440266059SGregory Neil Shapiro<h2> Function Reference </h2> 61540266059SGregory Neil Shapiro 61640266059SGregory Neil Shapiro<dl> 61740266059SGregory Neil Shapiro<dt> 61840266059SGregory Neil Shapiro<tt> SM_EXC_T *sm_exc_new_x(const SM_EXC_TYPE_T *type, ...) </tt> 61940266059SGregory Neil Shapiro<dd> 62040266059SGregory Neil Shapiro Create a new exception. Raise an exception on heap exhaustion. 62140266059SGregory Neil Shapiro The new exception has a reference count of 1. 62240266059SGregory Neil Shapiro <p> 62340266059SGregory Neil Shapiro 62440266059SGregory Neil Shapiro A list of zero or more exception arguments follows the exception type; 62540266059SGregory Neil Shapiro these are copied into the new exception object. 62640266059SGregory Neil Shapiro The number and types of these arguments is determined 62740266059SGregory Neil Shapiro by <tt>type->etype_argformat</tt>. 62840266059SGregory Neil Shapiro <p> 62940266059SGregory Neil Shapiro 63040266059SGregory Neil Shapiro Note that there is no rpool argument to sm_exc_new_x. 63140266059SGregory Neil Shapiro Exceptions are allocated directly from the heap. 63240266059SGregory Neil Shapiro This is because exceptions are normally raised at low levels 63340266059SGregory Neil Shapiro of abstraction and handled at high levels. Because the low 63440266059SGregory Neil Shapiro level code typically has no idea of how or at what level the 63540266059SGregory Neil Shapiro exception will be handled, it also has no idea of which resource 63640266059SGregory Neil Shapiro pool, if any, should own the exception. 63740266059SGregory Neil Shapiro <p> 63840266059SGregory Neil Shapiro<dt> 63940266059SGregory Neil Shapiro<tt> SM_EXC_T *sm_exc_addref(SM_EXC_T *exc) </tt> 64040266059SGregory Neil Shapiro<dd> 64140266059SGregory Neil Shapiro Increment the reference count of an exception. 64240266059SGregory Neil Shapiro Return the first argument. 64340266059SGregory Neil Shapiro <p> 64440266059SGregory Neil Shapiro<dt> 64540266059SGregory Neil Shapiro<tt> void sm_exc_free(SM_EXC_T *exc) </tt> 64640266059SGregory Neil Shapiro<dd> 64740266059SGregory Neil Shapiro Decrement the reference count of an exception. 64840266059SGregory Neil Shapiro If it reaches 0, free the exception object. 64940266059SGregory Neil Shapiro <p> 65040266059SGregory Neil Shapiro<dt> 65140266059SGregory Neil Shapiro<tt> bool sm_exc_match(SM_EXC_T *exc, const char *pattern) </tt> 65240266059SGregory Neil Shapiro<dd> 65340266059SGregory Neil Shapiro Compare the exception's category to the specified glob pattern, 65440266059SGregory Neil Shapiro return true if they match. 65540266059SGregory Neil Shapiro <p> 65640266059SGregory Neil Shapiro<dt> 65740266059SGregory Neil Shapiro<tt> void sm_exc_print(SM_EXC_T *exc, SM_FILE_T *stream) </tt> 65840266059SGregory Neil Shapiro<dd> 65940266059SGregory Neil Shapiro Print the exception on the stream 66040266059SGregory Neil Shapiro as a sequence of one or more newline terminated lines. 66140266059SGregory Neil Shapiro <p> 66240266059SGregory Neil Shapiro<dt> 66340266059SGregory Neil Shapiro<tt> void sm_exc_write(SM_EXC_T *exc, SM_FILE_T *stream) </tt> 66440266059SGregory Neil Shapiro<dd> 66540266059SGregory Neil Shapiro Write the exception on the stream without a terminating newline. 66640266059SGregory Neil Shapiro <p> 66740266059SGregory Neil Shapiro<dt> 66840266059SGregory Neil Shapiro<tt> void sm_exc_raise_x(SM_EXC_T *exc) </tt> 66940266059SGregory Neil Shapiro<dd> 67040266059SGregory Neil Shapiro Raise the exception. This function does not return to its caller. 67140266059SGregory Neil Shapiro <p> 67240266059SGregory Neil Shapiro<dt> 67340266059SGregory Neil Shapiro<tt> void sm_exc_raisenew_x(const SM_EXC_TYPE_T *type, ...) </tt> 67440266059SGregory Neil Shapiro<dd> 67540266059SGregory Neil Shapiro A short form for <tt>sm_exc_raise_x(sm_exc_new_x(type,...))</tt>. 67640266059SGregory Neil Shapiro</dl> 67740266059SGregory Neil Shapiro 67840266059SGregory Neil Shapiro<h2> Macro Reference </h2> 67940266059SGregory Neil Shapiro 68040266059SGregory Neil ShapiroThe SM_TRY ... SM_END_TRY control structure 68140266059SGregory Neil Shapiroensures that cleanup code is executed in the presence of exceptions, 68240266059SGregory Neil Shapiroand permits exceptions to be handled. 68340266059SGregory Neil Shapiro 68440266059SGregory Neil Shapiro<blockquote><pre> 68540266059SGregory Neil ShapiroSM_TRY 68640266059SGregory Neil Shapiro A block of code that may raise an exception. 68740266059SGregory Neil ShapiroSM_FINALLY 68840266059SGregory Neil Shapiro Cleanup code that may raise an exception. 68940266059SGregory Neil Shapiro This code is guaranteed to be executed whether or not 69040266059SGregory Neil Shapiro an exception was raised by a previous clause. 69140266059SGregory Neil Shapiro You may have 0 or more SM_FINALLY clauses. 69240266059SGregory Neil ShapiroSM_EXCEPT(e, pat) 69340266059SGregory Neil Shapiro Exception handling code, which is triggered by an exception 69440266059SGregory Neil Shapiro whose category matches the glob pattern 'pat'. 69540266059SGregory Neil Shapiro The exception value is bound to the local variable 'e'. 69640266059SGregory Neil Shapiro You may have 0 or more SM_EXCEPT clauses. 69740266059SGregory Neil ShapiroSM_END_TRY 69840266059SGregory Neil Shapiro</pre></blockquote> 69940266059SGregory Neil Shapiro 70040266059SGregory Neil ShapiroFirst, the SM_TRY clause is executed, then each SM_FINALLY clause is 70140266059SGregory Neil Shapiroexecuted in sequence. 70240266059SGregory Neil ShapiroIf one or more of these clauses was terminated by an exception, 70340266059SGregory Neil Shapirothen the first such exception is remembered, and the other exceptions 70440266059SGregory Neil Shapiroare lost. 70540266059SGregory Neil Shapiro 70640266059SGregory Neil ShapiroIf no exception was raised, then we are done. 70740266059SGregory Neil Shapiro 70840266059SGregory Neil ShapiroOtherwise, each of the SM_EXCEPT clauses is examined in sequence. 70940266059SGregory Neil Shapiroand the first SM_EXCEPT clause whose pattern argument matches the exception 71040266059SGregory Neil Shapiro(see <tt>sm_exc_match</tt>) is executed. 71140266059SGregory Neil ShapiroIf none of the SM_EXCEPT clauses matched the exception, or if there are 71240266059SGregory Neil Shapirono SM_EXCEPT clauses, then the remembered exception is re-raised. 71340266059SGregory Neil Shapiro 71440266059SGregory Neil Shapiro<p> 71540266059SGregory Neil ShapiroSM_TRY .. SM_END_TRY clauses may be nested arbitrarily. 71640266059SGregory Neil Shapiro 71740266059SGregory Neil Shapiro<p> 71840266059SGregory Neil ShapiroIt is illegal to jump out of a SM_TRY or SM_FINALLY clause 71940266059SGregory Neil Shapirousing goto, break, continue, return or longjmp. 72040266059SGregory Neil ShapiroIf you do this, you will corrupt the internal exception handling stack. 72140266059SGregory Neil ShapiroYou can't use <tt>break</tt> or <tt>continue</tt> in an SM_EXCEPT clause; 72240266059SGregory Neil Shapirothese are reserved for use by the implementation. 72340266059SGregory Neil ShapiroIt is legal to jump out of an SM_EXCEPT clause using goto or return; 72440266059SGregory Neil Shapirohowever, in this case, you must take responsibility 72540266059SGregory Neil Shapirofor freeing the exception object. 72640266059SGregory Neil Shapiro 72740266059SGregory Neil Shapiro<p> 72840266059SGregory Neil ShapiroThe SM_TRY and SM_FINALLY macros contain calls to setjmp, 72940266059SGregory Neil Shapiroand consequently, they suffer from the limitations imposed on setjmp 73040266059SGregory Neil Shapiroby the C standard. 73140266059SGregory Neil ShapiroSuppose you declare an auto variable <tt>i</tt> outside of a 73240266059SGregory Neil ShapiroSM_TRY ... SM_END_TRY statement, initializing it to 0. 73340266059SGregory Neil ShapiroThen you modify <tt>i</tt> inside of a SM_TRY or SM_FINALLY clause, 73440266059SGregory Neil Shapirosetting it to 1. 73540266059SGregory Neil ShapiroIf you reference <tt>i</tt> in a different SM_FINALLY clause, or in 73640266059SGregory Neil Shapiroan SM_EXCEPT clause, then it is implementation dependent whether <tt>i</tt> 73740266059SGregory Neil Shapirowill be 0 or 1, unless you have declared <tt>i</tt> to be <tt>volatile</tt>. 73840266059SGregory Neil Shapiro 73940266059SGregory Neil Shapiro<blockquote><pre> 74040266059SGregory Neil Shapiroint volatile i = 0; 74140266059SGregory Neil Shapiro 74240266059SGregory Neil ShapiroSM_TRY 74340266059SGregory Neil Shapiro i = 1; 74440266059SGregory Neil Shapiro ... 74540266059SGregory Neil ShapiroSM_FINALLY 74640266059SGregory Neil Shapiro /* the following reference to i only works if i is declared volatile */ 74740266059SGregory Neil Shapiro use(i); 74840266059SGregory Neil Shapiro ... 74940266059SGregory Neil ShapiroSM_EXCEPT(exc, "*") 75040266059SGregory Neil Shapiro /* the following reference to i only works if i is declared volatile */ 75140266059SGregory Neil Shapiro use(i); 75240266059SGregory Neil Shapiro ... 75340266059SGregory Neil ShapiroSM_END_TRY 75440266059SGregory Neil Shapiro</pre></blockquote> 75540266059SGregory Neil Shapiro 75640266059SGregory Neil Shapiro</body> 75740266059SGregory Neil Shapiro</html> 758