aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-04 16:43:33 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-11-04 16:43:33 +0200
commit4274008d26a3cc0cee44e410655cf31f17eb75f6 (patch)
treef34acd69d2fd326fa99e65233d6bac4bac1b5149
parent9ce3f39943eee5fb703a86ece6c80f8f72ca74b6 (diff)
downloadmailfromd-4274008d26a3cc0cee44e410655cf31f17eb75f6.tar.gz
mailfromd-4274008d26a3cc0cee44e410655cf31f17eb75f6.tar.bz2
Improve docs.
* NEWS, doc/deprecate.texi, doc/mailfromd.texi: Document new features. * doc/sexp.texi: New file. * doc/upgrade.texi: Update. * mfd/bi_msg.m4 (message_read_line) (message_read_body_line): Raise eof exception when there are no more lines left.
-rw-r--r--NEWS9
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/deprecate.texi67
-rw-r--r--doc/mailfromd.texi492
-rw-r--r--doc/sexp.texi65
-rw-r--r--doc/upgrade.texi14
-rw-r--r--mfd/bi_msg.m44
7 files changed, 551 insertions, 101 deletions
diff --git a/NEWS b/NEWS
index 671c99b8..9e922958 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Mailfromd NEWS -- history of user-visible changes. 2009-10-20
+Mailfromd NEWS -- history of user-visible changes. 2009-11-04
Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
See the end of file for copying conditions.
@@ -40,7 +40,7 @@ the source. Starting with this release the script file is renamed to
`mailfromd.rc' is recognized and parsed. This ensures backward
compatibility.
-** Pies removed
+** Pies withdrawn
The `pies' utility has been removed from the package. It is moved
into a stand-alone package called `Pies'. See
@@ -85,6 +85,11 @@ Use `.' operator instead. See `Explicit concatenation', below.
The `#require' keyword is deprecated. Use `require' instead.
See `Module system', for details.
+** message_read_line, message_read_body_line and EOF
+
+These functions raise EOF exception if there are no more lines to read.
+In previous version, e_io was signalled in this case.
+
* Upgrade procedure
To remove the deprecated features from your scripts and upgrade them
diff --git a/doc/Makefile.am b/doc/Makefile.am
index d8956df5..c5e409e6 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -25,6 +25,7 @@ mailfromd_TEXINFOS=\
pragma-database.texi\
pragma-option.texi\
rendition.texi\
+ sexp.texi\
smap.texi\
strftime.texi\
upgrade.texi\
diff --git a/doc/deprecate.texi b/doc/deprecate.texi
index 29e35a77..87f6af4f 100644
--- a/doc/deprecate.texi
+++ b/doc/deprecate.texi
@@ -23,13 +23,69 @@
@node implicit concatenation
@appendixsec Implicit Concatenation and Operational Syntax
-@UNREVISED
+ Implicit concatenation and operational syntax are two deprecated
+features still supported by @command{mailfromd} version
+@value{VERSION}. These features will disappear in the next release,
+so you are advised to update your scripts if they still use them.
+@xref{5x0-600, upgrade your scripts}, for a description of the upgrade
+procedure.
+
+ @dfn{Implicit concatenation} is performed wherever the compiler
+encounters two adjacent variables or adjacent variable and literal.
+Notice, that it does not affect implicit concatenation of adjacent
+literals, which is supported as before. That is, the following is
+correct:
+
+@smallexample
+ echo "GNU's" " not " " UNIX"
+@end smallexample
+
+@noindent
+whereas the following is deprecated:
+
+@smallexample
+ echo %y %z
+@end smallexample
+
+ When compiler encounters such a construct, it acts as if there were
+a @samp{.} (dot) operator between the variables
+(@pxref{Concatenation}), and issues the following warning:
+
+@smallexample
+@var{file}:@var{line}: implicit concatenation is deprecated
+@var{file}:@var{line}: use `.' operator
+@end smallexample
-@quotation
-@i{It seemed like a good idea at the time.}@*
-Brian Kernighan
-@end quotation
+ @dfn{Operationa syntax} consists in calling a function of one
+argument without parentheses around the actual parameter, e.g.:
+
+@smallexample
+ set x primitive_hostname $client_addr
+@end smallexample
+
+@noindent
+instead of:
+
+@smallexample
+ set x primitive_hostname($client_addr)
+@end smallexample
+
+ If such usage is encountered, the compiler issues the following
+warning:
+
+@smallexample
+@var{file}:@var{line}: use of function name as a prefix operator is
+deprecated
+@end smallexample
+
+ Both features brought more trouble than advantage, and therefore
+I decided to remove them. Please, update your scripts, if you are
+still using them. For the sake of completeness, here is what
+the documentation for previous versions of @command{mailfromd}
+said on the subject:
+
+@quotation
There are some features of @acronym{MFL} which, when used improperly,
may lead to subtle, hard identifiable errors. These are: concatenation
operation (@pxref{Concatenation}) and passing arguments to
@@ -55,6 +111,7 @@ doubt, parenthesize:
echo toupper("some" "thing") @result{} "SOMETHING"
echo toupper("some") "thing" @result{} "SOMEthing"
@end smallexample
+@end quotation
@node old-style function declarations
@appendixsec Old-Style Function Declarations
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index b1bf4772..efa1b985 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -121,8 +121,9 @@ Appendices
* Gacopyz::
* Time and Date Formats::
-* Upgrading::
+* s-expression::
* Deprecated Features::
+* Upgrading::
* Copying This Manual:: The GNU Free Documentation License.
* Concept Index:: Index of Concepts.
@@ -158,6 +159,7 @@ Tutorial
* SMTP Timeouts::
* Avoiding Verification Loops::
* HELO Domain::
+* rset::
* Controlling Number of Recipients::
* Sending Rate::
* Greylisting::
@@ -269,7 +271,7 @@ Expressions
* Constant expressions:: String and Numeric Constants.
* Function calls:: A Function Call is an Expression.
-* Concatenation:: Adjacent Expressions Concatenate.
+* Concatenation:: String Concatenation.
* Arithmetic operations:: @samp{+}, @samp{-}, etc.
* Relational expressions:: @samp{=}, @samp{<}, etc.
* Special comparisons:: @code{matches}, @code{mx matches}, etc.
@@ -287,10 +289,17 @@ Statements
@c Conditionals
@c Exception handlers
+Modules
+
+* module structure:: Declaring Modules
+* scope of visibility::
+* import:: Require and Import
+
Configuring @command{mailfromd}
* conf-types:: Special Configuration Data Types
* conf-base:: Base Mailfromd Configuration
+* conf-milter:: Milter Connection Configuration
* conf-debug:: Logging and Debugging configuration
* conf-timeout:: Timeout Configuration
* conf-callout:: Call-out Configuration
@@ -348,9 +357,13 @@ Deprecated Features
* pragma-option::
* pragma-database::
+* implicit concatenation::
+* old-style function declarations::
+* operational notation::
Upgrading
+* 5x0-600:: Upgrading from 5.x to 6.0
* 500-510:: Upgrading from 5.0 to 5.1
* 440-500:: Upgrading from 4.4 to 5.0
* 43x-440:: Upgrading from 4.3.x to 4.4
@@ -1139,6 +1152,7 @@ detailed discussion of the mail filtering language and
* SMTP Timeouts::
* Avoiding Verification Loops::
* HELO Domain::
+* rset::
* Controlling Number of Recipients::
* Sending Rate::
* Greylisting::
@@ -1292,7 +1306,7 @@ be rejected. When returned by any other handler,
it causes the whole message will be rejected.
The @code{reject} and @code{tempfail} actions executed by
-@code{helo} handler do not take effect immediately. Instead their
+@code{helo} handler do not take effect immediately. Instead, their
action is deferred until the next @acronym{SMTP} command from the
client, which is usually @code{MAIL FROM}.
@@ -1504,7 +1518,7 @@ as a statement.
@cindex built-in and library functions, introduced
@cindex library and built-in functions, introduced
@cindex module, defined
-@cindex #require, introduced
+@kwindex require
@command{Mailfromd} comes with a rich set of predefined functions
for various purposes. There are two basic function classes:
@dfn{built-in} functions, that are implemented by the @acronym{MFL}
@@ -1515,18 +1529,18 @@ calling them. In contrast, the library functions are defined in
@dfn{modules}, special @acronym{MFL} source files that contain functions
designed for a particular task. In order to access a library
function, you must first @dfn{require} a module it is defined in.
-This is done using @code{#require} statement. For example, the
+This is done using @code{require} statement. For example, the
function @code{hostname} looks up in the @acronym{DNS} the name
corresponding to the @acronym{IP} address specified as its argument. This
function is defined in module @file{dns.mf}, so before calling it you
must require this module:
@smallexample
-#require dns
+require dns
@end smallexample
@noindent
-The @code{#require} statement takes a single argument: the name of the
+The @code{require} statement takes a single argument: the name of the
requested module (without the @samp{.mf} suffix). It looks up the
module on disk and loads it if it is available.
@@ -1926,6 +1940,42 @@ done
@end group
@end smallexample
+@node rset
+@section SMTP RSET and Milter Abort Handling
+@cindex RSET
+@cindex milter abort
+ In previous section we have used a global variable to hold certain
+information and share it between hanlders. In the majority of cases,
+such information is session specific, and becomes invalid if the
+remote party issues the SMTP @code{RSET} command. Therefore,
+@command{mailfromd} clears all global variables when it receives a
+Milter @samp{abort} request, which is normally generated by this
+command.
+
+@kwindex precious
+@cindex precious variables
+@cindex variable, precious
+ However, you may need some variables that will retain their values
+even across SMTP session resets. In @command{mailfromd} terminology
+such variables are called @dfn{precious}. Precious variables are
+declared by prefixing their declaration with the keyword
+@code{precious}. Consider, for example, this snippet of code:
+
+@smallexample
+precious number rcpt_counter
+
+prog envrcpt
+do
+ set rcpt_counter %rcpt_counter + 1
+done
+@end smallexample
+
+ Here, the variable @samp{rcpt_counter} is declared as precious and
+its value is incremented each time the @samp{envrcpt} handler is
+called. This way, @samp{rcpt_counter} will keep the total number of
+SMTP @code{RCPT} commands issued during the session, no matter how
+many times it was restarted using the @code{RSET} command.
+
@node Controlling Number of Recipients
@section Controlling Number of Recipients
@@ -2075,7 +2125,7 @@ returns @code{False} and does not update the database.
following statement somewhere at the beginning of your script:
@smallexample
-#require rateok
+require rateok
@end smallexample
For example, the following code limits the mail sending rate for each
@@ -2085,7 +2135,7 @@ temporary failure response:
@smallexample
@group
-#require rateok
+require rateok
prog envfrom
do
@@ -2755,6 +2805,22 @@ expecting OR or AND or ')'
@end group
@end smallexample
+@xopindex{location-column, described}
+ The error location is indicated by the name of the file and the
+number of the line when the error occurred. By using the
+@option{--location-column} option you instruct @command{mailfromd} to
+also print the @dfn{column number}. E.g. with this option the above
+error message may look like:
+
+@smallexample
+@group
+mailfromd: /etc/mailfromd.mf:39:12 syntax error, unexpected ACT_REJECT,
+expecting OR or AND or ')'
+@end group
+@end smallexample
+
+ Here, @samp{39} is the line and @samp{12} is the column number.
+
@cindex cross-reference
For complex scripts you may wish to obtain a listing of variables
used in the script. This can be achieved using @option{--xref}
@@ -3587,14 +3653,16 @@ debugging, or in your @code{catch} statements.
@node Notes
@section Notes and Cautions
-@UNREVISED
- Another place to execute special caution are format strings used
-with @code{sprintf} (@pxref{String formatting}) and @code{strftime}
+ This section discussess some potential culprits in the
+@acronym{MFL}.
+
+ It is important to execute special caution when writing format
+strings for @code{sprintf} (@pxref{String formatting}) and @code{strftime}
(@pxref{strftime}) functions. They use @samp{%} as a character
introducing conversion specifiers, while the same character is used to
expand a @acronym{MFL} variable within a string. To prevent this
-misinterpretation, enclose format specification in @emph{single
+misinterpretation, always enclose format specification in @emph{single
quotes} (@pxref{singe-vs-double}). To illustrate this, let's consider
the following example:
@@ -4360,13 +4428,15 @@ result in raising a @code{e_macroundef} exception at the run time
Constants are defined using @code{const} statement:
@smallexample
-const @var{name} @var{expr}
+[@var{qualifier}] const @var{name} @var{expr}
@end smallexample
@noindent
where @var{name} is an identifier, and @var{expr} is any valid
@acronym{MFL} expression evaluating immediately to a constant literal
-or numeric value.
+or numeric value. Optional @var{qualifier} defines the scope of
+visibility for that constant (@pxref{scope of visibility}): either
+@code{public} or @code{static}.
@cindex constants, using in program text
After defining, any appearance of @var{name} in the program text is
@@ -4522,27 +4592,40 @@ These memory regions are identified by @dfn{variable names}. A
variable name must begin with a letter or underscore and must consist
of letters, digits and underscores.
- Each variable is associated with its @dfn{lexical scope}, i.e. the
-part of source code where it can be used. Depending on the scope we
-discern two main classes of variables: global and automatic ones.
+@cindex scope of visibility, variables
+@cindex variable lexical scope
+@anchor{variable scope}
+ Each variable is associated with its @dfn{scope of visibility},
+which defines the part of source code where it can be used
+(@pxref{scope of visibility}). Depending on the scope we discern
+three main classes of variables: public, static and automatic (or local).
+
+ @dfn{Public variables} have indefinite lexical scope, so they may
+be referred to anywhere in the program. @dfn{Static} are variables
+visible only within their module (@pxref{Modules}). @dfn{Automatic}
+or @dfn{local variables} are visible only within the given function or
+handler.
- @dfn{Global variables} have indefinite lexical scope, so they may
-be referred to anywhere in the program. @dfn{Automatic} or @dfn{local
-variables} are visible only within the given function or handler.
+ Public and static variables are sometimes collectively called
+@dfn{global}.
- The two variable classes occupy separate @dfn{namespaces}, so that an
-automatic variable can have the same name as an existing global one.
-In this case this variable is said to @dfn{shadow} its global
+ These variable classes occupy separate @dfn{namespaces}, so that an
+automatic variable can have the same name as an existing public or
+static one. In this case this variable is said to @dfn{shadow} its global
counterpart. All references to such a name will refer to the automatic
variable until the end of its scope is reached, where the global one
becomes visible again.
+ Likewise, a static variable may have the same name as a static
+variable defined in another module. However, it may not have the
+same name as a public variable.
+
@cindex variables, declaring
@cindex variable declarations
A variable is @dfn{declared} using the following syntax:
@smallexample
-@var{type} @var{name}
+[@var{qualifiers}] @var{type} @var{name}
@end smallexample
@noindent
@@ -4556,7 +4639,36 @@ variables and @samp{number} for numeric ones.
string var
@end smallexample
- Declaration can be followed by any valid @acronym{MFL}
+@cindex qualifiers, variable declaration
+@kwindex public
+@kwindex static
+Optional @var{qualifiers} are allowed only in global declarations, i.e.
+in the variable declarations that appear outside of functions. They
+specify the scope of the variable. The @code{public} qualifier
+declares the variable as public and the @code{static} qualifier
+declares it as static. The default scope is @samp{public},
+unless specified otherwise in the module declaration (@pxref{module
+structure}).
+
+@kwindex precious
+@cindex variables, precious
+Additionally, @var{qualifiers} may contain the word @code{precious},
+which instructs the compiler to mark this variable as @dfn{precious}.
+(@pxref{rset,, precious variables}). If both scope qualifier and
+@code{precious} are used, they may appear in any order, e.g.:
+
+@smallexample
+static precious string rcpt_list
+@end smallexample
+
+@noindent
+or
+
+@smallexample
+precious static string rcpt_list
+@end smallexample
+
+ The declaration can be followed by any valid @acronym{MFL}
expression, which supplies the @dfn{initial value} for the
variable, for example:
@@ -5651,7 +5763,7 @@ module (@pxref{Modules}).
Examples:
@smallexample
-#require strip_domain_part
+require strip_domain_part
strip_domain_part("puszcza.gnu.org.ua", 2) @result{} "org.ua"
strip_domain_part("puszcza.gnu.org.ua", 0) @result{} "gnu.org.ua"
@end smallexample
@@ -5666,7 +5778,7 @@ function is defined in @file{is_ip.mf} module (@pxref{Modules}).
For example:
@smallexample
-#require is_ip
+require is_ip
is_ip("1.2.3.4") @result{} 1
is_ip("1.2.3.x") @result{} 0
@@ -6386,8 +6498,7 @@ message_lines(@var{x}) = message_body_lines(@var{x})
@deftypefn {Built-in Function} string message_read_body_line (number @var{nmsg})
Read and return next line from the body of message @var{nmsg}. If
-there are no more lines to read, raise the @code{not_found} exception.
-@FIXME{Probably a special exception type is needed for that.}
+there are no more lines to read, raise the @code{eof} exception.
Use @code{message_body_rewind} (see above) to rewind the body stream
and read its contents again.
@@ -6395,7 +6506,7 @@ and read its contents again.
@deftypefn {Built-in Function} string message_read_line (number @var{nmsg})
Read and return next line from message @var{nmsg}. If
-there are no more lines to read, raise the @code{not_found} exception.
+there are no more lines to read, raise the @code{eof} exception.
Use @code{message_rewind} to rewind the message stream and read its
contents again.
@@ -6654,7 +6765,7 @@ without throwing exceptions.
available after requesting @file{dns.mf} module (@pxref{Modules}):
@smallexample
-#require dns
+require dns
@end smallexample
@deftypefn {Built-in Function} string dns_getaddr (string @var{domain})
@@ -6695,7 +6806,7 @@ getmx("org.pl") @result{} ""
@emph{Notes}:
@enumerate 1
@item The @code{getmx} function returns at most 32 @acronym{MX} names or @acronym{IP} addresses.
-@FIXME{This limit should probably be configurable.}
+@FIXME{This limit should be configurable.}
@item The number of items returned by @code{getmx(@var{domain})} can
differ from that obtained from @code{getmx(@var{domain}, 1)}, e.g.:
@@ -7124,7 +7235,7 @@ interfaces, which return cleanly if the @samp{e_dbfailure} exception
occurs. To use these interfaces, request the @file{safedb.mf} module:
@smallexample
-#require safedb
+require safedb
@end smallexample
The exception-safe interfaces are:
@@ -7456,7 +7567,7 @@ If it does not return a meaningful value, @code{localdomain} calls
the machine, and returns its domain part.
To use this function, require @file{localdomain.mf} module
-(@pxref{Modules}), e.g.: @code{#require localdomain}.
+(@pxref{Modules}), e.g.: @code{require localdomain}.
@end deftypefn
@deftypefn {Built-in Function} number time ()
@@ -7934,7 +8045,7 @@ we advise to use the @code{rateok} function, described below.
@flindex rateok.mf
To use this function, require @file{rateok.mf} module
-(@pxref{Modules}), e.g.: @code{#require rateok}.
+(@pxref{Modules}), e.g.: @code{require rateok}.
The @code{rateok} function returns @samp{True} if the mail sending
rate for @var{key}, computed for the interval of @var{sample-interval}
@@ -8015,7 +8126,7 @@ To use this function, require @file{valid_domain.mf} module
(@pxref{Modules}):
@smallexample
-#require valid_domain
+require valid_domain
@end smallexample
@end deftypefn
@@ -8461,7 +8572,7 @@ verification in @code{envfrom} handler:
@smallexample
#include_once <status.mfh>
-#require spf
+require spf
prog envfrom
do
@@ -8846,7 +8957,7 @@ the message domain. By default @var{dirname} is
To summarize all the above, the usual @acronym{NLS} setup will look like:
@smallexample
-#require nls
+require nls
begin
do
@@ -9087,7 +9198,7 @@ invoked.
@cindex @code{func} statement, function definition
@smallexample
@group
-func @var{name} (@var{param-decl}) returns @var{data-type}
+[@var{qualifier}] func @var{name} (@var{param-decl}) returns @var{data-type}
do
@var{function-body}
done
@@ -9108,6 +9219,23 @@ Variable declarations}), i.e.:
declares the parameter @var{name} having the type @var{type}. The
@var{type} is @code{string} or @code{number}.
+@cindex qualifier, function declaration
+@kwindex public
+@kwindex static
+@cindex scope of visibility, functions
+@anchor{function scope of visibility}
+ Optional @var{qualifier} declares the scope of visibility for that
+function (@pxref{scope of visibility}). It is similar to that of
+variables, except that functions cannot be local (i.e. you cannot
+declare function within another function).
+
+ The @code{public} qualifier declares a function that may be referred
+to from any module, whereas the @code{static} qualifier declares a
+function that may be called only from the current module
+(@pxref{Modules}). The default scope is @samp{public},
+unless specified otherwise in the module declaration (@pxref{module
+structure}).
+
For example, the following declares a function @samp{sum}, that takes
two numeric arguments and returns a numeric value:
@@ -9115,6 +9243,12 @@ two numeric arguments and returns a numeric value:
func sum(number x, number y) returns number
@end smallexample
+ Similarly, the following is a declaration of a static function:
+
+@smallexample
+static func sum(number x, number y) returns number
+@end smallexample
+
Parameters are referenced in the @var{function-body} by their name,
using the syntax for variable references: @code{%@var{name}}. The
value of a parameter can be altered using @code{set} statement, the
@@ -9365,8 +9499,8 @@ shows definitions of some of the library functions shipped with
@command{mailfromd}. These functions are contained in modules
installed along with the @command{mailfromd} binary. To use any of
them in your code, require the appropriate module as described in
-@FIXME-ref{require}, e.g. to use the @code{revip}
-function, do @code{require 'revip'}.
+@ref{import}, e.g. to use the @code{revip} function, do
+@code{require 'revip'}.
Functions and their definitions:
@@ -9432,7 +9566,7 @@ definition follows:
@smallexample
@group
-#require dns
+require dns
func valid_domain(string domain) returns number
do
@@ -9448,8 +9582,8 @@ The function @code{match_dnsbl} (@pxref{match_dnsbl}) is defined as
follows:
@smallexample
-#require dns
-#require match_cidr
+require dns
+require match_cidr
#pragma regex push +extended
func match_dnsbl(string address, string zone, string range)
@@ -9495,7 +9629,7 @@ assigned to a variable or passed to a function.
@menu
* Constant expressions:: String and Numeric Constants.
* Function calls:: A Function Call is an Expression.
-* Concatenation:: Adjacent Expressions Concatenate.
+* Concatenation:: String Concatenation.
* Arithmetic operations:: @samp{+}, @samp{-}, etc.
* Relational expressions:: @samp{=}, @samp{<}, etc.
* Special comparisons:: @code{matches}, @code{mx matches}, etc.
@@ -9817,7 +9951,7 @@ String concatenation
@cindex type casts, implicit
@cindex implicit type casts
When two operands on each side of a binary expression have
-different type, @command{mailfromd} evaluator has to coerce them to a
+different type, @command{mailfromd} evaluator coerces them to a
common type. This is known as @dfn{implicit type casting}. The rules
for implicit type casting are:
@@ -9843,6 +9977,7 @@ left-hand side argument.
@cindex type casts, explicit
@cindex explicit type casts
+@anchor{explicit type casts}
The construct for explicit type cast is:
@smallexample
@@ -10975,8 +11110,8 @@ nested statements. @FIXME{Elaborate on that.}
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 should be fixed in
-future releases.}
+invent your own exception types. @FIXME{This is fixed in the
+@samp{mtax-cleanup} branch.}
@node Polling
@section Sender Verification Tests
@@ -11225,31 +11360,202 @@ done
@section Modules
@cindex module, defined
- A module is an @acronym{MFL} source file containing a collection of
-conceptually united functions and data. Currently, there are no
-special syntax rules that make an arbitrary source file a module, it
-suffices to make sure the module name ends in standard suffix
-@samp{.mf} and place it in one of the directories comprising the include
-source path (@pxref{include search path}). However, such syntax rules
-will appear in future versions. It is planned that modules will be
-compiled and stored on disk in form of object files or combined into
-libraries.
+ A @dfn{module} is a logically isolated part of code that implements a
+separate concern or feature and contains a collection of conceptually
+united functions and/or data. Each module occupies a separate
+compilation unit (i.e. file). The functionality provided by
+a module is incorporated into another module or the main program by
+@dfn{requiring} this module or by @dfn{importing} the desired
+components from it.
- In order to make definitions from module @file{@var{modname}.mf}
-available to your filter program, use the following statement:
+@menu
+* module structure:: Declaring Modules
+* scope of visibility::
+* import:: Require and Import
+@end menu
+
+@node module structure
+@subsection Declaring Modules
+@cindex module declaration
+@kwindex module
+ A module file must begin with a @dfn{module declaration}:
@smallexample
-#require @var{modname}
+module @var{modname} [@var{interface-type}].
@end smallexample
-@FIXME{require}
-@ignore
-The @code{#require} statement looks up the module
-@file{@var{modname}.mf} in the include path and attempts to compile
-it (@pxref{require}). It is not an error to require the same module
-several times. However, requiring a non-existing module results in
-compilation error.
-@end ignore
+ Note the final dot.
+
+The @var{modname} parameter declares the name of the module. It is
+recommended that it be the same as the file name without the
+@samp{.mf} extension. The module name must be a valid @acronym{MFL}
+literal. It also must not coincide with any defined @acronym{MFL}
+symbol, therefore we recommend to always quote it (see example below).
+
+The optional parameter @var{interface-type} defines the @dfn{default
+scope of visibility} for the symbols declared in this module. If it is
+@samp{public}, then all symbols declared in this module are made
+public (importable) by default, unless explicitly declared otherwise
+(@pxref{scope of visibility}). If it is @samp{static}, then all
+symbols, not explicitly marked as public, become static. If the
+@var{interface-type} is not given, @samp{public} is assumed.
+
+The actual @acronym{MFL} code follows the @samp{module} line.
+
+The module definition is terminated by the @dfn{logical end} of its
+compilation unit, i.e. either by the end of file, or by the
+keyword @code{bye}, whichever occurs first.
+
+@kwindex bye
+Special keyword @code{bye} may be used to prematurely end the current
+compilation unit before the physical end of the containing file.
+Any material between @code{bye} and the end of file is ignored by the
+compiler.
+
+Let's illustrate these concepts by writing a module @samp{revip}:
+
+@smallexample
+@group
+module 'revip' public.
+
+func revip(string ip)
+ returns string
+do
+ return inet_ntoa(ntohl(inet_aton(%ip)))
+done
+
+bye
+
+This text is ignored. You may put any additional
+documentation here.
+@end group
+@end smallexample
+
+@node scope of visibility
+@subsection Scope of Visibility
+@cindex scope of visibility
+ @dfn{Scope of Visibility} of a symbol defines from where this symbol
+may be referred to. Symbols in @acronym{MFL} may have either of the
+following two scopes:
+
+@table @dfn
+@item Public
+ Public symbols are visible from the current module, as well as from
+any external modules, including the main script file, provided that
+they are properly imported (@pxref{import}).
+
+@item Static
+ Static symbols are visible only from the current module. There is
+no way to refer to them from outside.
+@end table
+
+ The default scope of visibility for all symbols declared within
+a module is defined in the module declaration (@pxref{module
+structure}). It may be overridden for any individual symbol by
+prefixing its declaration with an appropriate @dfn{qualifier}: either
+@code{public} or @code{static}.
+
+@node import
+@subsection Require and Import
+@cindex importing from modules
+@cindex requiring modules
+ Functions or variables declared in another module must be @dfn{imported}
+prior to their actual use. @acronym{MFL} provides two ways of doing
+so: by @dfn{requiring} the entire module or by importing selected
+symbols from it.
+
+@deffn {Module Import} require modname
+ The @code{require} statement instructs the compiler to locate the
+module @var{modname} and to load all public interfaces from it.
+@end deffn
+
+ The compiler looks for the file @file{@var{modname}.mf} in the
+current search path (@pxref{include search path}). If no such file
+is found, a compilation error is reported.
+
+ For example, the following statement:
+
+@smallexample
+require revip
+@end smallexample
+
+@noindent
+imports all interfaces from the module @file{revip.mf}.
+
+@kwindex from
+@kwindex import
+@cindex @code{from @dots{} import}
+ Another, more sophisticated way to import from a module is to use
+the @samp{from ... import} construct:
+
+@smallexample
+from @var{module} import @var{symbols}.
+@end smallexample
+
+Note the final dot. The @samp{from} and @samp{module} statements are
+the only two constructs in @acronym{MFL} that require the delimiter.
+
+The @var{module} has the same semantics as in the @code{require}
+construct. The @var{symbols} is a comma-separated list of symbol
+names to import from @var{module}. A symbol name may be given in
+several forms:
+
+@enumerate 1
+@item Literal
+
+Literals specify exact symbol names to import. For example,
+the following statement imports from module @file{A.mf} symbols
+@samp{foo} and @samp{bar}:
+
+@smallexample
+from A import foo,bar.
+@end smallexample
+
+@item Regular expression
+
+Regular expressions must be surrounded by slashes. A regular
+expression instructs the compiler to import all symbols whose
+names match that expression. For example, the following statement
+imports from @file{A.mf} all symbols whose names begin with @samp{foo}
+and contain at least one digit after it:
+
+@smallexample
+from A import '/^foo.*[0-9]/'.
+@end smallexample
+
+The type of regular expressions used in the @samp{from} statement is
+controlled by @code{#pragma regex} (@pxref{regex}).
+
+@item Regular expression with transformation
+
+Regular expression may be followed by a @dfn{s-expression}, i.e. a
+@command{sed}-like expression of the form:
+
+@smallexample
+s/@var{regexp}/@var{replace}/[@var{flags}]
+@end smallexample
+
+@noindent
+where @var{regexp} is a @dfn{regular expression}, @var{replace} is a
+replacement for each part of the input that matches @var{regexp}.
+S-expressions and their parts are discussed in detail in
+@ref{s-expression}.
+
+The effect of such construct is to import all symbols that match the
+regular expression and apply the s-expression to their names.
+
+For example:
+
+@smallexample
+from A import '/^foo.*[0-9]/s/.*/my_&/'.
+@end smallexample
+
+This statement imports all symbols whose names begin with @samp{foo}
+and contain at least one digit after it, and renames them, by prefixing
+their names with the string @samp{my_}. Thus, if @file{A.mf} declared a
+function @samp{foo_1}, it becomes visible under the name of @samp{my_foo_1}.
+
+@end enumerate
@node Preprocessor
@section @acronym{MFL} Preprocessor
@@ -11420,12 +11726,15 @@ with this option, because @command{mailfromd} cannot verify whether
@node Filter Script Example
@section Example of a Filter Script File
- This section will show a working example of the filter script file.
-For the ease of illustration, it is divided in several sections.
-Each section is prefaced with a comment explaining its function.
+ In this section we will discuss a working example of the filter
+script file. For the ease of illustration, it is divided in several
+sections. Each section is prefaced with a comment explaining its
+function.
-@FIXME{Example of config:
+ This filter assumes that the @file{mailfromd.conf} file contains the
+following:
+@smallexample
relayed-domain-file (/etc/mail/sendmail.cw,
/etc/mail/relay-domains);
io-timeout 33;
@@ -11433,9 +11742,14 @@ database cache @{
negative-expire-interval 1 day;
positive-expire-interval 2 weeks;
@};
-}
+@end smallexample
+
+ Of course, the exact parameter settings may vary, what is important
+is that they be declared. @xref{Mailfromd Configuration}, for a
+description of @command{mailfromd} configuration file syntax.
- The first part defines the configuration settings for this host:
+ Now, let's return to the script. Its first part defines the
+configuration settings for this host:
@smallexample
#pragma regex +extended +icase
@@ -11915,10 +12229,10 @@ Mailutils Manual}.
@node conf-types
@section Special Configuration Data Types
-@UNREVISED
- In addition to the usual mailutils data types (@pxref{S