diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-07-14 23:35:18 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-07-14 23:35:18 +0300 |
commit | 8d4894458790db74d795e874c298b0810aca7746 (patch) | |
tree | ef5a30b144afdc0980bb2a2ccfc8ced68b526963 | |
parent | 439316ca0f68a32663e8bffdcb6b6f0e9e6d091f (diff) | |
download | mailfromd-8d4894458790db74d795e874c298b0810aca7746.tar.gz mailfromd-8d4894458790db74d795e874c298b0810aca7746.tar.bz2 |
Document try-catch and dclex
* NEWS: Update.
* doc/mailfromd.texi: Document try-catch and dclex.
* doc/upgrade.texi : Update.
* doc/values.texi (MIN_EXCEPTION, MAX_EXCEPTION): New values.
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | doc/mailfromd.texi | 265 | ||||
-rw-r--r-- | doc/upgrade.texi | 4 | ||||
-rw-r--r-- | doc/values.texi | 2 |
4 files changed, 183 insertions, 96 deletions
@@ -168,6 +168,10 @@ identifier may then be used in `catch' and `throw' statements, e.g.: throw myerror "My error encountered" +For a detailed discussion, see the manual, subsection 4.18.2 +"User-defined Exceptions". +FIXME: Before release, check if the subsection number is right. + ** The try-catch construct This version introduces a `try-catch' construct similar to that used @@ -193,6 +197,10 @@ STMTLIST-2. The `try-catch' construct allows a better and more flexible error recovery. +For a detailed discussion, see the manual, subsection 4.18.3 +"Exception Handling". +FIXME: Before release, check if the subsection number is right. + ** Handling of stderr in open("|...") If open call is used to start external program (i.e. its argument diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 30bfc8db..92dbfa5b 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi @@ -248,6 +248,12 @@ Statements @c Conditionals @c Exception handlers +Exceptional Conditions + +* Built-in Exceptions:: +* User-defined Exceptions:: +* Catch and Throw:: + Modules * module structure:: Declaring Modules @@ -4991,8 +4997,9 @@ lookup fails, @samp{$1} will contain the message sender's @acronym{IP} address enclosed in square brackets (e.g. @samp{[127.0.0.1]}). @item @code{number}; -Socket address family. Include @file{status.mfh} to get symbolic -definitions for the address families. Supported families are: +Socket address family. You need to require the @samp{status} module +to get symbolic definitions for the address families. Supported +families are: @cindex FAMILY_STDIO @cindex FAMILY_UNIX @@ -7094,19 +7101,31 @@ return a boolean value. However, when querying the Domain Name System, it may fail to get a definite result. For example, the @acronym{DNS} server can be down or temporary unavailable. In other words, @code{primitive_hasmx} can be in a situation when, instead of returning -@samp{yes} or @samp{no}, it has to return @samp{don't know}. That is -exactly then when it signals an @dfn{exception}. +@samp{yes} or @samp{no}, it has to return @samp{don't know}. It has +no way of doing so, therefore it signals an @dfn{exception}. -@anchor{status.mfh} +@anchor{status.mf} @cindex exception types -@cindex @file{status.mfh}, header file +@cindex @file{status.mf}, module @cindex exceptions, symbolic names - Exceptions are identified by @dfn{exception types}, the decimal -numbers associated with them. The header file @file{status.mfh} -defines @dfn{symbolic exception names} for each of these. The + Each exception is identified by @dfn{exception type}, an integer +number associated with it. + +@menu +* Built-in Exceptions:: +* User-defined Exceptions:: +* Catch and Throw:: +@end menu + +@node Built-in Exceptions +@subsection Built-in Exceptions +The numbers from @value{MIN_EXCEPTION} to @value{MAX_EXCEPTION} are +reserved for @dfn{built-in exceptions}. The module @file{status.mf} +defines @dfn{symbolic exception names} for each of these. The following table summarizes all the exception types implemented by @command{mailfromd} version @value{VERSION}: +@anchor{exception names} @table @code @cindex e_dbfailure, exception type @item e_dbfailure @@ -7224,6 +7243,39 @@ was not found. @xref{figure-poll-wrapper}, for an illustration on how these can be used. For consistency with other exception codes, these can be spelled as @code{e_success} and @code{e_not_found}. +@node User-defined Exceptions +@subsection User-defined Exceptions +@kwindex dclex + You can define your own exception types using the @code{dclex} +statement: + +@smallexample +dclex @var{type} +@end smallexample + +In this statement, @var{type} must be a valid @acronym{MFL} +identifier, not used for another constant (@pxref{Constants}). +The @code{dclex} statement defines a new exception identified by +the constant @var{type} and allocates a new exception number for it. + +The @var{type} can subsequently be used in @code{throw} and +@code{catch} statements, for example: + +@smallexample +dclex myrange + +number fact(number val) + returns number +do + if val < 0 + throw myrange "fact argument is out of range" + fi + @dots{} +done +@end smallexample + +@node Catch and Throw +@subsection Exception Handling @cindex exceptions, default handling @cindex default exception handling Normally when an exception is signalled, the program execution is @@ -7233,15 +7285,21 @@ to the logging channel (@pxref{Logging and Debugging}). However, the user can intercept any exception by installing his own exception-handling routines. +@cindex @code{try} statement @cindex @code{catch} statement +@cindex try-catch construct @cindex exception-handling routines @cindex exception handlers @kwindex catch - An exception-handling routine is introduced by @code{catch} + An exception-handling routine is introduced by a @dfn{try-catch} statement, which has the following syntax: @smallexample @group +try +do + @var{stmtlist} +done catch @var{exception-list} do @var{handler-body} @@ -7250,99 +7308,102 @@ done @end smallexample @noindent -where @var{exception-list} is the list of exception types, separated -by the word @code{or}. A special form @samp{*}, which stands for -all exceptions, is allowed as well. The @var{handler-body} is the list of -statements comprising the handler body. For example, the code below -installs a handler for exceptions 2 (@samp{e_failure}) and 3 -(@samp{e_temp_failure}): +where @var{stmtlist} and @var{handler-body} are sequences of +@acronym{MFL} statements and @var{exception-list} is the list of +exception types, separated by the word @code{or}. A special +@var{exception-list} @samp{*} is allowed and means all exceptions. -@smallexample -@group -catch 2 or 3 -do - @dots{} -done -@end group -@end smallexample +This construct works as follows. First, the statements from +@var{stmtlist} are executed. If the execution finishes +successfully, control is passed to the first statement after the +@samp{catch} block. Otherwise, if an exception is signalled and this +exception is listed in @var{exception-list}, the execution is passed to the +@var{handler-body}. If the exception is not listed in +@var{exception-list}, it is handled as usual. -@noindent -@anchor{exception symbolic names} -@cindex @file{status.mfh}, usage - However, using numeric exception codes is not convenient and is not -in fact recommended. We recommend to use exception symbolic names -instead. These are declared in the header file @file{status.mfh}, which -should be included in your startup script. Using this approach, the -above code snippet will look like: + The following example shows a @samp{try-catch} construct used for +handling seventual exceptions, signalled by @code{primitive_hasmx}. @smallexample @group -#include <status.mfh> - +try +do + if primitive_hasmx(domainpart($f)) + accept + else + reject + fi +done catch e_failure or e_temp_failure do - @dots{} + echo "primitive_hasmx failed" + continue done @end group @end smallexample - + @cindex scope of exception handlers @cindex scope of a @code{catch} @cindex @code{catch} scope @cindex exception handler scope - The @code{catch} statement can appear anywhere inside a function or + The @samp{try-catch} statement can appear anywhere inside a function or a handler, but it cannot appear outside of them. It can also be nested -within another @code{catch}. Each exception redefined by a catch -remains in force until either another catch appears further in the -same function or handler that redefines it or an end of the containing -block is encountered, whichever occurs first. Upon exit from a +within another @samp{try-catch}, in either of its parts. Upon exit from a function or milter handler, all exceptions are restored to the state they had when it has been entered. +@cindex catch, standalone +@cindex standalone catch + A @code{catch} block can be used alone, without preceding @code{try} +part. Such a construct is called a @dfn{standalone catch}. It is +mostly useful for setting global exception handlers in a @code{begin} +statement (@pxref{begin/end}). When used within a usual function or +handler, the exception handlers set by a standalone catch +remain in force until either another standalone catch appears further +in the same function or handler, or an end of the function is +encountered, whichever occurs first. + + A standalone catch defined within a function must return from +it by executing @code{return} statement. If it does not do that +explicitly, the default value of 1 is returned. A standalone catch +defined within a milter handler must end execution with any of the +following actions: @code{accept}, @code{continue}, @code{discard}, +@code{reject}, @code{tempfail}. By default, @code{continue} is +used. + + It is not recommended to mix @samp{try-catch} constructs and +standalone catches. If a standalone catch appears within a +@samp{try-catch} statement, its scope of visibility is undefined. + @cindex returning from a catch @cindex returning from an exception handler @cindex @code{catch}, returning from @cindex exception handler, returning from @cindex @code{catch} arguments @cindex arguments, @code{catch} - Upon entry to a @code{catch} code, it receives two positional -arguments, which can be referenced in @var{handler-body} as @code{$1} + Upon entry to a @var{handler-body}, two implicit positional arguments +are defined, which can be referenced in @var{handler-body} as @code{$1} and @code{$2}. The first argument gives the numeric code of the exception that has occurred. The second argument is a textual string -containing a human-readable description of the exception. A -@code{catch} defined within a function must return from -it by executing @code{return} statement. If it does not do that -explicitly, the default value of 1 is returned. A @code{catch} -defined within a milter handler must end execution with any of the -following actions: @code{accept}, @code{continue}, @code{discard}, -@code{reject}, @code{tempfail}. By default, @code{continue} is -used. +containing a human-readable description of the exception. - The following example shows an @code{envfrom} handler that catches -eventual exceptions, signaled by @code{primitive_hasmx}. The handler -accepts the message if the sender domain has any @samp{MX} records, rejects -them if it does not, and continues execution if an exception occurs. -In the latter case, a log message is also issued: + The following is an improved version of the previous example, which +uses these parameters to supply more information about the failure: @smallexample -@group -#include <status.mfh> - -prog envfrom +try do - catch e_failure or e_temp_failure - do - echo "Caught exception $1: $2" - continue - done - if primitive_hasmx(domainpart($f)) accept else reject fi done -@end group +catch e_failure or e_temp_failure +do + echo "Caught exception $1: $2" + continue +done @end smallexample @cindex @code{hasmx}, definition of the function @@ -7352,28 +7413,42 @@ false if it does not or if an exception occurs @footnote{This function is part of the @code{mailfromd} library, @xref{hasmx}.}. @smallexample -@group -func hasmx (s) returns n +func hasmx (string s) + returns number do + try + do + return primitive_hasmx(domainpart(s)) + done catch * do return 0 done - return primitive_hasmx(domainpart($1)) done -@end group @end smallexample + The same function can written using standalone @code{catch}: + +@smallexample +func hasmx (string s) + returns number +do + catch * + do + return 0 + done + return primitive_hasmx(domainpart(s)) +done +@end smallexample + + @cindex @code{catch}, accessing variables from @cindex variables, accessing from @code{catch} @cindex accessing variables from @code{catch} All variables remain visible within @code{catch} body, with the -exception of positional arguments of the enclosing function or -handler. So, if you wish to access function arguments from a -@code{catch}, define your function using new style -(@pxref{User-defined}) declaration. To access positional -arguments of a handler, you will have to assign them to local -variables prior to installing a catch, e.g.: +exception of positional arguments of the enclosing handler. To access +positional arguments of a handler from the @code{catch} body, assign +them to local variables prior to the @samp{try-catch} construct, e.g.: @smallexample @group @@ -7381,13 +7456,16 @@ prog header do string hname $1 string hvalue $2 + try + do + @dots{} + done catch * do echo "Exception $1 while processing header %hname: %hvalue" echo $2 tempfail done - @dots{} @end group @end smallexample @@ -7396,24 +7474,21 @@ do @cindex raising exceptions @kwindex throw You can also generate (or @dfn{raise}) exceptions explicitly in the -filter code, using @code{throw} statement: +code, using @code{throw} statement: @smallexample throw @var{excode} @var{descr} @end smallexample - The arguments correspond exactly to the positional arguments of the + The arguments correspond exactly to the positional parameters of the @code{catch} statement: @var{excode} gives the numeric code of the exception, @var{descr} gives its textual description. This statement can be used in complex scripts to create non-local exits from deeply nested statements. @FIXME{Elaborate on that.} - Notice several limitations of @code{throw}: first, the @var{excode} -argument must be an immediate value, you cannot use an expression in -its place. Secondly, its range is limited to exception codes, -described in @ref{status.mfh}. In other words, you cannot (yet) -invent your own exception types. @FIXME{This is fixed in the -@samp{mtax-cleanup} branch.} + Notice, that the the @var{excode} argument must be an immediate +value: an exception identifier (either built-in one or one declared +previously using a @code{dclex} statement). @node Polling @section Sender Verification Tests @@ -7446,10 +7521,18 @@ done @code{catch}, for example thus: @smallexample -#include <status.mfh> +require status prog envfrom do + try + do + if stdpoll($1, ehlo_domain, mailfrom_address) == 0 + accept + else + reject 550 5.1.0 "Sender validity not confirmed" + fi + done catch e_failure or e_temp_failure do switch $1 @@ -7460,12 +7543,6 @@ do tempfail 450 4.1.0 "Try again later" done done - - if stdpoll($1, ehlo_domain, mailfrom_address) == 0 - accept - else - reject 550 5.1.0 "Sender validity not confirmed" - fi done @end smallexample @@ -7555,7 +7632,7 @@ done @noindent The @var{condition} is either a function call or a special @code{poll} statement (see below). The values used in @code{when} branches are -normally symbolic exception names (@pxref{exception symbolic names}). +normally symbolic exception names (@pxref{exception names}). When the compiler processes the @code{on} statement it does the following: diff --git a/doc/upgrade.texi b/doc/upgrade.texi index d95fdad4..929dff86 100644 --- a/doc/upgrade.texi +++ b/doc/upgrade.texi @@ -278,7 +278,7 @@ variables, which remained unnoticed in previous releases. To minimize chances of name clashes, all symbolic exception codes has been renamed by prefixing them with the @samp{e_}, thus, e.g. @code{divzero} became @code{e_divzero}, etc. The @code{ioerr} exception code is renamed to -@code{e_io}. @xref{status.mfh}, for a full list of the new exception codes. +@code{e_io}. @xref{status.mf}, for a full list of the new exception codes. @cindex @code{OLD_EXCEPTION_CODES}, preprocessor symbol For consistency, the following most often used codes are available without @@ -386,7 +386,7 @@ non-blocking syslog}. predefined symbolic names for exception codes (previous versions used the @samp{&} prefix to dereference them). Instead, it relies on constants defined in the include file @file{status.mfh} -(@pxref{status.mfh}). +(@pxref{status.mf}). However, the script files from 3.1 series will still work, but the following warning messages will be displayed: diff --git a/doc/values.texi b/doc/values.texi index ca2ef0ef..3991640d 100644 --- a/doc/values.texi +++ b/doc/values.texi @@ -9,3 +9,5 @@ @set GACOPYZ_READ_TIMEOUT 10 seconds @set GACOPYZ_EOM_TIMEOUT 5 minutes @set GACOPYZ_CONNECT_TIMEOUT 5 minutes +@set MIN_EXCEPTION 0 +@set MAX_EXCEPTION 16 |