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.