Anatomy of a Librified Function in libarch, tla-1.3.x
3 Mar 2005
Nearly all new functionns in librified tla will be examples of
filling in a single template. The template relies on a set
of CPP macros and provides a framework for raising and handling
error conditions and for robustly releasing allocated resources
when they are no longer needed.
Here is a short form of the template:
ssize_t
@FNNAME@ (t_arch const arch)
{
ARCH_FN_DECLS(@FNNAME@);
ARCH_FN_ENTRY
{}
ARCH_FN_CLEANUPS
{}
ARCH_FN_NORMAL_EXIT
{
invariant (answer >= 0);
}
ARCH_FN_ERRORS
{}
ARCH_FN_BODY
{}
ARCH_FN_END;
}
and here is a commented version:
/* All functions return a value of type `ssize_t'.
* Negative return values indicate an error condition.
*
* All functions accept a parameter of type type `t_arch'.
* That parameter *must* (for various macros to work) be
* named `arch'. (Functions may accept additional parameters
* as well, of course.)
*/
ssize_t
@FNNAME@ (t_arch const arch)
{
ARCH_FN_DECLS(@FNNAME@);
/*
* The above macro expands to declarations needed by other
* `ARCH_FN_' macros.
*/
/* Here, declare all non-const local variables, regardless of
* their block scope. Every variable must be initialized and
* the initialization expression must not contain any function
* calls:
*/
/* The first line of non-declaration code must be:
*/
ARCH_FN_ENTRY
{
/* Here, complete initialization of locals.
* This section is often empty.
*
* It is best practice to *not* put code here which
* can fail (detect an error condition).
*
* Execution of this code is followed by execution
* of the function body (see ARCH_FN_BODY, below).
*/
}
ARCH_FN_CLEANUPS
{
/* All exit paths from the function (both normal
* returns and error conditions) pass through
* this section of code.
*
* Use it to release all resources held by local
* variables.
*/
}
ARCH_FN_NORMAL_EXIT
{
/* Normal exit paths (not error conditions)
* pass through this block.
*
* State invariants relating to the return value.
* If it is especially convenient, computed values
* may be copied into return parameters here and the
* `ssize_t' return value may be canonicalized.
*
* The value that will be returned after leaving this
* section is stored in the variable `answer', declared
* above by `ARCH_FN_DECLS'.
*
* Note that *all* functions are subject to the invariant
* that `answer >= 0' but some functions may impose
* additional constraints.
*
* Note also that these constraints do not mean the function
* can not return a negative value. If this function
* exits via `ARCH_RAISE' or `ARCH_RERAISE' (see below) then
* it return a negative error code.
*/
invariant (answer >= 0);
/* Execution of this section is followed first by
* execution of the `ARCH_FN_CLEANUPS' section and
* then by a /C/ `return'.
}
ARCH_FN_ERRORS
{
/* List all errors this function might raise and whether or
* not it might reraise an error raised by a function it
* calls.
*/
ARCH_CAN_RAISE(EFATAL);
ARCH_CAN_RAISE(ENOMEM);
ARCH_CAN_RAISE(EARCHPARAMS);
}
ARCH_FN_BODY
{
/* The body of the function goes here.
* Execution of this section follows that of
* the `ARCH_FN_ENTRY' section, above.
*
* A statement of the form:
*
* ARCH_RAISE (ERRORNAME);
*
* raises the arch error named `ERRORNAME' (see
* `libarch/arch.h' for a list of such errors).
* `ARCH_RAISE' is a macro which does not "return" -- it
* transfters control to the `ARCH_FN_CLEANUPS' section.
*
* If the body calls another function which return a
* negative error code, this function can re-raise the
* same error by invoking:
*
* ARCH_RERAISE;
*
* Before raising an error, formatted error message text
* can be recorded using:
*
* arch_msgbuf_printfmt (arch, "format string", ...);
*
* The body must *not* contain a `return' statement.
* Instead, the form:
*
* ARCH_RETURN ( VALUE );
*
* should be used.
*
* Alternatively, functions can exit by assigning a return
* value to the variable `answer' and either executing:
*
* ARCH_NORMAL_EXIT;
*
* or reaching the final `ARCH_FN_END'.
*/
}
ARCH_FN_END;
}
Copyright
Copyright (C) 2004 Tom Lord
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
See the file COPYING for further information about
the copyright and warranty status of this work.