# BlockManager.java

    /*
    ** Module   : BlockManager.java
    ** Abstract : common "scaffolding" for executing Progress-compatible code blocks
    **
    ** Copyright (c) 2008-2025, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- ----------------------------------Description-----------------------------------
    ** 001 GES 20080509   @38517 Created initial version. Implements the core
    **                           "scaffolding" for executing 4GL-compatible
    **                           code blocks. The API is designed to handle
    **                           all possible block constructs and for the
    **                           converted code to delegate the execution of
    **                           those code blocks to this class. This greatly
    **                           reduces the amount of code in the converted
    **                           business logic.
    ** 002 GES 20080619   @38884 Now provides more detailed block types to the
    **                           transaction manager. ON ENDKEY UNDO, RETRY is
    **                           now signalled to the TM as well.
    ** 003 GES 20080625   @38958 Shifted the TM to the BlockType enum and
    **                           moved the enum to be a separate class.
    ** 004 GES 20080701   @39058 FOR blocks/loops must honor user-defined
    **                           ENDKEY behavior in preference to the default
    **                           behavior for a query "off end".
    ** 005 GES 20080818   @39433 Added some UNDO stmt signatures. Fix to add
    **                           the error prop to DO blocks/loops that are
    **                           full transactions (it is implicit).
    ** 006 GES 20080822   @39519 Added missing function for GO-ON editing
    **                           blocks, implicit ERROR property support for
    **                           DO blocks/loops that are marked as FULL
    **                           transaction types AND ILP support to convert
    **                           NEXT to LEAVE.
    ** 007 GES 20080829   @39694 Added honorStop() support.
    ** 008 GES 20080924   @39934 Fix for QueryOffEndException processing.
    **                           It must always cause a FOR loop or block
    **                           to UNDO, LEAVE.
    ** 009 SIY 20081003   @40016 Added notification of listeners about
    **                           conditions triggered in blocks to which they
    **                           are bound.
    ** 010 GES 20081106   @40361 Editing blocks must handle an error generated
    **                           by the END-ERROR key by re-throwing it (just
    **                           as is done in the UPDATE stmt). This needs
    **                           to be done for all forms of editing block,
    **                           not just one with the UPDATE stmt.
    ** 011 SIY 20081111   @40412 Added UNKNOWN Condition type, changed
    **                           visibility of exceptionToCondition, other
    **                           minor cleanups.
    ** 012 GES 20081126   @40740 Fixes for interactions counter and END-ERROR
    **                           processing in EDITING and DO blocks/loops.
    ** 013 GES 20090115   @41132 Fix for loophole in condition processing.
    **                           If processCondition() is about to re-throw
    **                           an exception, it must trigger abnormalEnd()
    **                           processing first.
    ** 014 SVL 20090415   @41799 Fixed error handing for editing blocks.
    ** 015 GES 20090512   @42148 Added execution statistics support.
    ** 016 CA  20090727   @43396 When a query associated or nested with a FOR
    **                           or FOR EACH block goes off end, its
    **                           associated buffers must not process the
    **                           undoables (the buffer must not reference any
    **                           record after the UNDO, LEAVE).
    ** 017 GES 20090729   @43443 Added validation processing hooks at the end of
    **                           every block or loop, just before normal exit or
    **                           iteration.
    ** 018 CA  20090731   @43471 Fixed query off-end processing. When the query
    **                           for a FOR or FOR EACH block finds no more records,
    **                           the loop must be allowed to finish, by performing
    **                           the implicit END-KEY action (UNDO, LEAVE), even
    **                           if the user has defined an explicit END-KEY
    **                           action. For END-KEY conditions generated by a FIND
    **                           statement, the block must execute the default
    **                           END-KEY action if no explicit one is defined.
    **                           Else, it must execute the user-defined action.
    ** 019 CA  20090804   @43505 Fixed undo, leave when used inside a FOR block.
    **                           Cleanup TM related static imports. Fixed PRESELECT
    **                           query in DO/REPEAT blocks - the record buffers
    **                           associated with the query must not reference any
    **                           record until a FIND statement is executed on the
    **                           buffer.
    ** 020 ECF 20090816   @43656 Fixed output parameter support for database
    **                           fields. Modified topLevelBlock() and
    **                           functionBlock() to call out to the current
    **                           block's OutputParameterAssigner, if any, to copy
    **                           output parameters' values back to the database
    **                           fields with which they are associated.
    ** 021 GES 20090831   @43801 Don't raise ERROR in caller if the called code is a function.
    ** 022 CA  20130123          Pass the Block instance to pushScope, so it will be saved by the
    **                           BlockDefinition. Added APIs to support functions returning rowid,
    **                           recid and int64 values.
    ** 023 CA  20130129          Added "function returns longchar" support.
    ** 024 CA  20130209          Added support for functions returning extent.  Refactored the
    **                           function call APIs to use generics.
    ** 025 CA  20130315          Added returnNormal(WrappedResource) API, to be used when the HANDLE
    **                           attribute is used by this statement (in this case, HANDLE returns a
    **                           WrappedResource and not a real handle).
    ** 025 OM  20130329          Added returnNormal (long val) since decimal variant loses precision.
    **                           Fixed return type in functionBlock() by applying "conversion"
    **                           constructor if needed.
    ** 026 CA  20131116          Fixed pushing of the TARGET- and SOURCE-PROCEDURE for java-style
    **                           function calls.
    ** 027 CA  20140218          Resolved PROGRAM-NAME in case of java-style function calls: push to
    **                           a dedicated stack the closest function name, before invoking the
    **                           function's body.
    ** 028 HC  20140708          Added support for error handling of the extent parameter wrapper
    **                           classes (AbstractExtentParameter).
    ** 029 SVL 20140709          Handle InvalidParameterConditionException in topLevelBlock.
    ** 030 ECF 20140813          Added processValidateWorker to preserve and restore certain work area
    **                           state which would otherwise be corrupted by database write triggers
    **                           being fired during validation processing.
    ** 031 VIG 20140709          Added ConditionException processing for _MSG function to
    **                           the processBody method.
    ** 032 GES 20141014          Added Block.fini() call support. It must be called every time the
    **                           body() is actually executed (no matter whether on the first
    **                           execution, an iteration, a retry or when the body is exiting
    **                           normally or abnormally.  In all cases there is a 1 to 1 association
    **                           of block body execution to fini method execution. This matches the
    **                           4GL FINALLY block feature.
    ** 033 GES 20150204          Clear GO-PENDING when a NEXT statement is used in an EDITING block.
    ** 034 CA  20150222          An EDITING block is a no-op if no widgets are specified (i.e. all
    **                           WHEN clauses are false).
    ** 036 OM  20150709          Added support for error conditions in OutputParameterAssigner.
    ** 037 CA  20150813          Improve performance of user-def function calls converted to java
    **                           method calls: the legacy function name is passed at the function
    **                           definition, to the function* emitted API.  If this is set, this will
    **                           avoid calling the expensive ProcedureManager.resolveClosestMethod.
    ** 038 ECF 20150815          Implemented more efficient reflection logic in functionBlock.
    ** 039 ECF 20160206          Pass exceptional cause of certain rollback operations to TM.
    ** 040 GES 20160518          Major rewrite to implement lambda expressions.
    ** 041 OM  20160906          Small optimization.
    ** 042 GES 20160830          Added support for Block.pre() to replace use of the default c'tor.
    **         20160907          Modified how the containing business logic instance is obtained for
    **                           an external procedure. When lambdas are used, this instance MUST be
    **                           passed through as a parameter to the externalProc() call.
    ** 043 CA  20180521          Added stopAfter stubs for DO's STOP-AFTER option.
    **     CA  20180528          Added UNLESS-HIDDEN to the UPDATE/SET/PROMPT-FOR ... EDITING blocks.
    ** 044 CA  20181216          Added ON ... THROW support and BLOCK-LEVEL and ROUTINE-LEVEL stmts.
    **                           Added stub for UNDO, THROW.
    **                           Added stub for CATCH statement.
    ** 045 CA  20190122          internalProcedure calls emitted for constructor or destructor methods
    **                           defined for a legacy 4GL class must specify the caller name and
    **                           either the instance or .class, to allow Java direct class.
    **     CA  20190219          Added runtime for ROUTINE-LEVEL ON ERROR UNDO,THROW and
    **                           BLOCK-LEVEL ON ERROR UNDO,THROW.
    **                           Basic runtime for legacy error management.
    **     GES 20190323          Reduced context local lookups.
    **     CA  20190324          Improved the statistics to record the execution time.
    **                           returnWorker now avoids building a Java array for all calls.
    **     GES 20190324          Implemented TransactionHelper instead of direct usage of the static
    **                           TM API.  This allows the elimination of context local usage in TM.
    **     CA  20190325          Implemented ProcedureHelper and ControlFlowOpsHelper instead of
    **                           direct usage of the static API.
    ** 046 CA  20190628          Track if an AppError is from a RETURN ERROR statement.
    ** 047 HC  20190701          Fixed returnError to allow raising any legacy error type. Added
    **                           marking of a returned object as 'pending-assign' to prevent deletion
    **                           of the object before is is returned to the caller.
    ** 048 CA  20190710          Added API to get the return value from a function (if it applies).
    **     CA  20190720          Always load a legacy class, if a static method is accessed.
    ** 049 AIL 20190917          Added the ValidationUnwindException handling inside the blocks.
    **         20191119          Replaced ValidationUnwindException with default on error throw
    **     CA  20191119          Track the executing legacy class, to be able to register any buffer
    **                           to its source definition class.
    **     GES 20191122          Added processCatch().
    ** 050 CA  20200122          Javadoc fixes.
    **     CA  20200312          Fixes for UNDO, THROW and RETURN ERROR, in case when a OO-like
    **                           error condition needs to be generated.
    **     CA  20200324          More fixes related to OO-like error processing via AppError.
    **     CA  20200330          More fixes related to OE-compatible error management, in constructor
    **                           case and 'implicit' 4GL ERROR conditions.
    **     CA  20200407          ERROR conditions generated by the FWD runtime must be deferred, so
    **                           that they can be emitted by the client-side, too.
    **     CA  20200427          Replaced isValid().booleanValue() calls with _isValid().
    **     CA  20200528          undoThrowTopLevel must mark the AppError as 'from return', to be able to use the
    **                           return value message.
    ** 051 CA  20200713          Fixed 'RETURN ?' in a procedure - the RETURN-VALUE must be set to unknown.
    **     GES 20200731          Eliminated context-local lookups by using ErrorHelper.
    ** 052 CA  20200927          Use WorkArea.cfops.setReturnValue(String) instead of direct ControlFlowOps call.
    **     CA  20200927          Avoid context-local lookups by relying on the helper instance.
    **     CA  20210216          Arithmetic operations are always int64 - this requires special processing when
    **                           passing such an expression as an argument, so the conversion-time type of the
    **                           expression is preserved.  If the assignment of the argument fails, the top-level
    **                           must not be invoked.
    **     CA  20210310          Small performance improvement (avoid unnecessary setup if the block doesn't have
    **                           a fini method).
    **     SVL 20210316          Fixed RETURN NO-APPLY for persistent triggers.
    **     CA  20210428          A memptr returned by a function call must be the real reference, as a SET-SIZE
    **                           called on a OO property will change that property directly.
    **     CA  20210428          For function/OO calls passed as an argument to another call, evaluate them via a
    **                           lambda expression so that the 'output parameter assigner' is not corrupted.
    **     HC  20210511          Fixed widget display validation on GO event in EDITING block and
    **                           WAIT-FOR.
    **     CA  20210609          Reworked INPUT/INPUT-OUTPUT parameters to a new approach, where they are explicitly
    **                           initialized at the method's execution, and not at the caller's arguments.
    **                           (backed out CA/20210428).
    **     GES 20210809          Fixed FINALLY block to execute after commitables/finalizables are processed.
    **     OM  20211111          Added transaction support for FINALLY blocks.
    **     CA  20211112          Fixed RETURN-ERROR when this is done in the root procedure for a remote appserver
    **                           call (the error condition must be propagated to the remote side).
    **     OM  20211201          Improved transaction support for finally blocks.
    **     OM  20211130          Allow function return value to be overriden.
    **     CA  20220120          Performance improvement for pushing a new calee scope, keep the already resolved
    **                           internal entry legacy name.
    **     CA  20220120          When a legacy OO exception is consumed, release it so it can be deleted.
    **     CA  20220128          All non-empty messages in a thrown legacy error must be displayed, if the error
    **                           is not processed by a CATCH block.
    **     CA  20220208          Only RETURN ERROR can raise legacy OO errors on the caller's side for appserver
    **                           calls.
    **     CA  20220304          An ERROR condition being raised from within a block which can catch SysError must
    **                           be morphed into a legacy SysError exception, and not raise an ERROR condition.
    **     VVT 20220305          NPE in hasLegacyError fixed when method is called from JUnit.
    **     AL2 20220314          Poly functions shouldn't explicitly convert the return value.
    **                           Wrap return value in proxies to honor dynamic function behavior.
    **     CA  20220426          CATCH block can be nested, added a 'catchBlock' stub which will have the runtime
    **                           support for a CATCH block's default block.
    **     CA  20220531          Fixed propagation of explicit legacy exceptions - they must propagate if the
    **                           block has ON ERROR UNDO, THROW or if they are explicitly throw by the application.
    **     CA  20220606          Added lazy loading of legacy converted classes.
    **     TW  20220803          Error-status:error must be set for return error in method, while return error
    **                           in old-style ABL function must remain the same. Refs: #6567.
    **     TW  20220804          Harden against NPE.
    **     TW  20220817          Error-status:error must be set for return error in static method.
    **     CA  20220930          Added a helper to expose the context-local 'markPendingDynCall' API.
    **     CA  20220901          Refactored scope notification support: ScopeableFactory was removed, and the
    **                           registration is now specific to each type of scopeable.  For each case, the block
    **                           will be registered for scope support (for that particular scopeable) only when
    **                           the scopeable is 'active' (i.e. unnamed streams or accumulators are used).  This
    **                           allows a lazy registration of scopeables, to avoid the unnecessary overhead of
    **                           processing all the scopeables for each and every block.
    **     EVL 20221017          Fix from CA to protect from client silent abend for LegacyErrorException.
    **     TJD 20220504          Java 11 compatibility minor changes
    **     CA  20221123          If an 'object' instance is assigned in the FINALLY block and also referenced by
    **                           the RETURN statement, then do not remove it from 'pendingAssign'.
    **     CA  20220613          Allow OO exceptions to propagate to the remote side, when exiting the root block
    **                           on a appserver call.
    **     CA  20230116          Improvement from context-local state resolution.
    ** 053 GES 20230116          Avoid throw/catch for normal return in a function (performance optimization).
    **                           Added variants of returnNormal/returnExtentNormal called storeReturnValue/
    **                           storeExtentReturnValue to make the code read better (they are really the same
    **                           code at this point in time).
    ** 054 CA  20230307          For p2j.oo code, for now let returnNormal throw a ReturnUnwindException, as this
    **                           code is not refactored to use the GES/20230116 approach.
    ** 055 CA  20230313          A missed case for CA/20230307 - check static OO method calls, too, as the static
    **                           classes have a different registry in ObjectOps.
    ** 056 GBB 20230322          Log legacy error before throwing.
    ** 057 RAA 20230525          Creating a new BaseDataType instance is now done using BaseDataTypeFactory.
    ** 058 OM  20230505          Avoided incorrect INDEX_OUT_OF_RANGE exception.
    ** 059 CA  20230609          If a structured exception reaches a block with an ON ERROR clause with an action
    **                           something other than THROW, it will consume this legacy exception and treat it as
    **                           an ERROR condition.
    **     CA  20230615          The UNDO, THROW executed from a CATCH block must target the parent block of the
    **                           block where the CATCH was defined.  Also, the CATCH block must execute just
    **                           before the FINALLY block, in TM.popScope.
    **                           Small optimization - avoid using obj.ref() and use instead obj.ref, if the 'obj'
    **                           instance is known to be valid.
    ** 060 CA  202300707         A RETURN in a CATCH block associated with a top-level block will emit via
    **                           'storeReturnValue'; identify this call and treated as if it was from the top-level
    **                           block.
    **                           Also, clear any pending errors before the CATCH is executed.
    ** 061 CA  20230713          Fixed a regression in H059 and H060 - a RETURN from a CATCH block was leaking to
    **                           previous block and terminating it.
    **                           Other optimizations related to 'storeReturnValue' and basic processing of the
    **                           CATCH and FINALLY termination blocks.
    ** 062 AL2 20230801          Refactored looping blocks to allow query parameter.
    ** 063 ME  20230919          Wrap return value from functionBlock if return type is BaseDataType (invoke, poly).
    ** 064 OM  20230921          Added static method trigger().
    ** 065 CA  20231009          Fixed the 'executing' type for direct Java calls.
    ** 066 CA  20230919          Fixed a bug for direct Java call, the 'executing' type was not computed correctly.
    ** 067 CA  20230802          Ensure the OutputParameterAssigner gets reset if a legacy OO exception is thrown
    **                           in the FINALLY or CATCH block.
    ** 068 CA  20231026          An object instance being returned must be tracked on the caller block, as the
    **                           returned value may or may not be assigned, and the callee may return a freshly
    **                           created instance which will never gets discarded if is never assigned again.
    **                           Do not pin the Block instance to BlockDefinition, as it is never read.
    ** 068 CA  20231129          Use method references where possible.
    **     CA  20231216          'checkFunctionReturn' needs to process only the top of stack, as this is where
    **                           current return value can ever exist.
    **     CA  20231221          ObjectOps scopeable support is registered only when: a var is defined, a new
    **                           instance is being created, or a function/method returns 'object'.
    ** 069 AL2 20230801          Refactored looping blocks to allow query parameter.
    ** 070 ES  20231203          Added a new parameter for forBlock to allow multiple query directions.
    **     ES  20231212          Removed casting to CompundQuery in forEachWorker and forWorker.
    **     ES  20231213          Adding a switch in forBlockWorker to select operation performed on the query parameter.
    ** 071 AL2 20240221          Process the legacy exceptions to trigger rollbacks of the block it passes through.
    ** 072 SVL 20240207          Preserve case sensitivity of the returned character value of a function.
    ** 073 AL2 20240308          Rollback on legacy error exceptions only when a (sub-)transaction is active.
    **                           Don't let error condition exceptions enter abnormal handling with ON ... THROW.
    ** 074 AL2 20240229          Avoid roll-back on off-end query that was used for the for-each or for-block.
    **         20240311          Restore the processOffEndListeners calls; they are used to reset the off-end.
    ** 075 AL2 20240310          Validate at the end of a loop iteration even if not inside a transaction.
    ** 076 CA  20240324          Use logical constants for TRUE, FALSE, UNKNOWN, within internal FWD runtime.
    ** 077 ES  20240404          Set iteration flag for the query defined in FOR EACH block.
    ** 078 SC  20240516          Added a check for dynamic call in functionBlock and created a proxy if the
    **                           function return type is different from the returned value type
    ** 079 SB  20240523          Prevent rollback on legacy exception errors if there is a pending rollback.
    **                           Refs #8728.
    ** 080 CA  20240522          Ensure 'abort' is called for OutputParameterAssigner in case of errors during
    **                           pop scope processing (which includes catch/finally blocks).
    ** 081 DDF 20240523          Re-throw processed legacy error based on the reThrow flag of the error if possible.
    **     DDF 20240524          Revert re-throw change and avoid NPE when matching condition is null.
    ** 082 CA  20240529          Fixed SC/078 when there is direct java calls.
    ** 083 CA  20240609          Once a structured exception is re-thrown, mark it as explicit, so it can be
    **                           re-thrown via top-level blocks.
    ** 084 ES  20240513          Added support for stop-after statement for Progress blocks.
    **                           After each successful iteration of the block body the timer of the current block should
    **                           be cleaned.
    **                           Targeting the block for which stop-after timeout was raised.
    **                           If a inner block of a targeted by a stop-after block has an ON STOP, RETRY, then the
    **                           retry should be honored.
    **         20240531          Added support to disable stop-after runtime with a parameter in directory.
    **         20240604          Lazy initialization of the stopAfterTimer in WorkArea.
    ** 085 CA  20240708          A block needs to be aware if a RETURN ERROR or UNDO, THROW was used for exit,
    **                           as this will make a FINALLY block to act as if it executes in silent mode. Also,
    **                           a CATCH block will not be executed when RETURN ERROR or UNDO, THROW is used.
    ** 086 AS  20240730          Moved exitTopLevel to finally block in topLevelBlock
    ** 087 AS  20240911          Fixed error propagation for errors thrown in caller.
    ** 088 TJD 20240314          BufferManager should be pending scopeable for editing block, fix by CA
    **     TJD 20240409          Reset queryOffEnd listeners on beginning of foreach worker
    ** 089 ES  20240919          Prevent second rollback in case of an undoThrowTopLevel.
    ** 090 CA  20240625          Certain database-level ERROR conditions (like 132/buffer already exists with)
    **                           must be processed as if BLOCK-LEVEL ON ERROR UNDO, THROW is set (in other words,
    **                           it can get morphed into a strcutured exceptions).
    ** 091 AS  20241204          In LOG-MANAGER context, log the numbered errors thrown by undoThrow.
    ** 092 ES  20240115          In case the unnamed stream is redirected in the editiongBlock, call the
    **                           subsequent GenericFrame method (set, update or promtFor).
    ** 093 RNC 20250204          If the FOR-EACH query raises an error, leave the block instead of retrying.
    ** 094 CA  20250131          Added support for ON QUIT, {LEAVE|NEXT|...} - this must not rollback, but commit.
    ** 095 SP  20250210          Added storeReturnValue(Stream) and returnNormal(Stream) variants.
    ** 096 GBB 20250218          ErrorManager.displayError() calls moved to a new method displayErrorMessage,
    **                           where the legacy error is marked as displayed to avoid a second display.
    **                           Duplicated code refactored.
    ** 097 ES  20250217          Added support for nested catch blocks.
    ** 098 ES  20250227          Added runtime support for undo, throw with Progress.Lang.Stop error. Added methods
    **                           undoThrowStopTopLevel and undoThrowStop.
    **     ES  20250228          Added runtime supoort for UNDO, RETURN ERROR exe statement.
    */

    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, 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 Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.util;

    import java.util.*;
    import java.util.concurrent.*;
    import java.util.concurrent.atomic.*;
    import java.util.function.*;
    import java.util.logging.Level;
    import java.io.*;
    import java.lang.reflect.*;

    import com.goldencode.p2j.directory.*;
    import com.goldencode.p2j.main.*;
    import com.goldencode.p2j.net.Control;
    import com.goldencode.p2j.oo.lang.*;
    import com.goldencode.p2j.persist.*;
    import com.goldencode.p2j.security.ContextLocal;
    import com.goldencode.p2j.security.RestrictedUseException;
    // the following are dependencies on the UI package which we would prefer to
    // eliminate if the services can be cleanly abstracted without making the
    // calling code worse from a readability perspective
    import com.goldencode.p2j.ui.LogicalTerminal;
    import com.goldencode.p2j.util.ProcedureManager.ProcedureHelper;
    import com.goldencode.p2j.util.logging.CentralLogger;
    import com.goldencode.p2j.ui.CommonFrame;
    import com.goldencode.p2j.ui.FrameElement;
    import com.goldencode.p2j.ui.GenericFrame;
    import com.goldencode.p2j.ui.EventList;
    import com.goldencode.p2j.security.SecurityManager;
    import com.goldencode.util.*;

    import static com.goldencode.p2j.util.TransactionManager.*;

    /**
     * Provides an external API that allows the Progress-compatible code block
     * semantics to be provided with a minimum of code in the caller. This class
     * encodes the "scaffolding" necessary to properly process code blocks with
     * the right behavior.  The external interface is designed to be statically
     * imported to make access simple, short and easy to read. The API has been
     * designed to minimize name conflicts.  The scaffolding code uses the
     * {@link TransactionManager} extensively to implement the proper behavior.
     */
    public class BlockManager
    {
       /** Logger */
       private static final CentralLogger LOG = CentralLogger.get(BlockManager.class.getName());

       /** Stores context-local state variables. */
       private static final ContextContainer work = new ContextContainer();

       /** Encodes the possible levels of transaction support for each block. */
       public static enum TransactionType { NONE, SUB, FULL };

       /** Encodes the possible condition types. */
       public static enum Condition { ERROR, ENDKEY, STOP, QUIT, QUIT_COMMIT, UNKNOWN };

       /** Encodes the possible actions in response to given conditions. */
       public static enum Action
       {
          LEAVE,
          NEXT,
          RETRY,
          RETURN_NORMAL,
          RETURN_CONSUME,
          RETURN_ERROR,
          THROW
       }

       /** The fixed label of all FINALLY: blocks. */
       public static final String FINALLY_BLOCK_LABEL = "__finally__";

       /** The fixed label of all CATCH: blocks. */
       public static final String CATCH_BLOCK_LABEL = "__catch__";

       /** Encodes the possible types of return statement. */
       enum ReturnType { NORMAL, CONSUME, ERROR, STORE }

       /** Encodes the possible responses to a flow control event. */
       private static enum Disposition { BREAK, CONTINUE, THROW, NONE };

       /** Directory entry to define an execution statistics output file. */
       private static final String STATS_FILE = "block-execution-statistics";

       /** Synthetic null value to use in a deque which doesn't accept null values. */
       private static final Object NULL = new Object();

       /** Output filename in which to write execution statistics. */
       private static String statsFile = null;

       /** Stores calls execution statistics. */
       private static Map<String, AtomicInteger> stats = null;

       /** Stores timing execution statistics. */
       private static Map<String, AtomicLong> times = null;

       static
       {
          Directory dir = DirectoryManager.getInstance();
          statsFile = dir.getString(Directory.ID_RELATIVE, STATS_FILE, null);

          if (statsFile != null)
          {
             stats = new ConcurrentHashMap<String, AtomicInteger>();
             times = new ConcurrentHashMap<String, AtomicLong>();
             StandardServer.register(new StatsHelper());
          }
       }

       /**
        * API for ROUTINE-LEVEL ON ERROR UNDO,THROW statement.
        * <p>
        * This will change the default ON ERROR from UNDO, RETRY to UNDO, THROW for all routines
        * in this procedure or class (including its 'execute' method).
        * <p>
        * This includes:
        * <ul>
        *    <li>external program</li>
        *    <li>internal procedures</li>
        *    <li>functions </li>
        *    <li>user-defined functions</li>
        *    <li>class methods</li>
        *    <li>class constructors (but not destructors) - including static</li>
        *    <li>class property getter/setter - including static</li>
        *    <li>schema trigger programs - including static</li>
        * </ul>
        * TODO: does this affect super-classes, in case of OO instances?
        *
        * @param    condition
        *           ERROR.
        * @param    action
        *           THROW.
        */
       public static void onRoutineLevel(Condition condition, Action action)
       {
          // TODO: the condition/action currently is not propagated or saved - ERROR, THROW is always assumed
          work.get().pm.markRoutineLevelUndoThrow();
       }

       /**
        * API for BLOCK-LEVEL ON ERROR UNDO,THROW statement.
        * <p>
        * This will change the default ON ERROR from UNDO, RETRY to UNDO, THROW for all routines
        * in this procedure or class (including its 'execute' method).
        * <p>
        * This includes:
        * <ul>
        *    <li>external program</li>
        *    <li>internal procedures</li>
        *    <li>functions </li>
        *    <li>user-defined functions</li>
        *    <li>class methods</li>
        *    <li>class constructors (but not destructors) - including static</li>
        *    <li>class property getter/setter - including static</li>
        *    <li>schema trigger programs - including static</li>
        *    <li>REPEAT, FOR, DO TRANSACTION blocks</li>
        * </ul>
        * TODO: does this affect super-classes, in case of OO instances?
        *
        * @param    condition
        *           ERROR.
        * @param    action
        *           THROW.
        */
       public static void onBlockLevel(Condition condition, Action action)
       {
          // TODO: the condition/action currently is not propagated or saved - ERROR, THROW is always
          // assumed
          work.get().pm.markBlockLevelUndoThrow();
       }

       /**
        * Offers runtime support for stop-after statement for Progress blocks.
        *
        * @param    val
        *           The number of seconds to wait before raising a QUIT.
        */
       public static void stopAfter(NumberType val)
       {
          stopAfter(val.longValue());
       }

       /**
        * Offers runtime support for stop-after statement for Progress blocks.
        *
        * @param    val
        *           The number of seconds to wait before raising a QUIT.
        */
       public static void stopAfter(long val)
       {
           WorkArea wa = work.get();

           if (!wa.isStopAfterActive || val == 0)
           {
              return;
           }

           if (wa.stopAfterTimer == null)
           {
              try
              {
                 Control control = SecurityManager.getCurrentContextControl();
                 String threadName = Thread.currentThread().getName();
                 wa.stopAfterTimer = new StopAfterTimer(threadName, control);
                 wa.errHelper.setStopAfterTimer(wa.stopAfterTimer);
                 wa.tm.registerStopAfterTimer(wa.stopAfterTimer);
              }
              catch (RestrictedUseException e)
              {
                 LOG.log(Level.WARNING,
                       "Restricted use of Control.getCurrentContextControl()",
                       e);
                 return;
              }
           }

           StopAfterTimer stopAfterTimer = wa.stopAfterTimer;
           BlockDefinition block = wa.tm.getBlock();

           if (stopAfterTimer.isBlockRegistered(block))
           {
              return;
           }

           StopAfterTimer.Task task = stopAfterTimer.addTimeOut(block, val);
           wa.tm.registerFinalizable(task, false);
       }

       /**
        * Execute the given external procedure block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        * <p>
        * This form may only be used with block instances that are anonymous inner classes since
        * the containing business logic class can be calculated using reflection. Any usage with
        * lambdas will fail!
        *
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(Block block)
       {
          externalProcedure(null, null, TransactionType.SUB, block);
       }

       /**
        * Execute the given external procedure block with the given transaction level.
        * <p>
        * This form may only be used with block instances that are anonymous inner classes since
        * the containing business logic class can be calculated using reflection. Any usage with
        * lambdas will fail!
        *
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(TransactionType lvl, Block block)
       {
          externalProcedure(null, null, lvl, block);
       }

       /**
        * Execute the given external procedure block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        * <p>
        * This form is suitable for use with lambdas but in such a case the <code>referent</code>
        * must be non-null.
        *
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  If this is non-null, then <code>block</code> can be an instance created
        *           using lambdas.  If <code>null</code>, then <code>block</code> MUST BE an
        *           anonymous inner class of the containing business logic instance so that instance
        *           can be calculated via reflection.
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(Object referent, Block block)
       {
          externalProcedure(referent, TransactionType.SUB, block);
       }

       /**
        * Execute the given external procedure block with the given transaction level.
        * <p>
        * This form is suitable for use with lambdas but in such a case the <code>referent</code>
        * must be non-null.
        *
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  If this is non-null, then <code>block</code> can be an instance created
        *           using lambdas.  If <code>null</code>, then <code>block</code> MUST BE an
        *           anonymous inner class of the containing business logic instance so that instance
        *           can be calculated via reflection.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(Object referent, TransactionType lvl, Block block)
       {
          // TODO: move this in a more performance-wise place (i.e. after user login and Agent.listen)

          // ensure certain context-local data has loaded
          ProcedureManager.load();

          topLevelBlock(null, referent, null, lvl, BlockType.EXTERNAL_PROC, block);
       }

       /**
        * Execute the given external procedure block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        * <p>
        * This form is suitable for use with lambdas but in such a case the <code>referent</code>
        * must be non-null.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  If this is non-null, then <code>block</code> can be an instance created
        *           using lambdas.  If <code>null</code>, then <code>block</code> MUST BE an
        *           anonymous inner class of the containing business logic instance so that instance
        *           can be calculated via reflection.
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(Class<?> def,
                                            Object referent,
                                            Block block)
       {
          externalProcedure(def, referent, TransactionType.SUB, block);
       }

       /**
        * Execute the given external procedure block with the given transaction level.
        * <p>
        * This form is suitable for use with lambdas but in such a case the <code>referent</code>
        * must be non-null.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  If this is non-null, then <code>block</code> can be an instance created
        *           using lambdas.  If <code>null</code>, then <code>block</code> MUST BE an
        *           anonymous inner class of the containing business logic instance so that instance
        *           can be calculated via reflection.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void externalProcedure(Class<?> def,
                                            Object referent,
                                            TransactionType lvl,
                                            Block block)
       {
          // TODO: move this in a more performance-wise place (i.e. after user login and Agent.listen)

          // ensure certain context-local data has loaded
          ProcedureManager.load();

          topLevelBlock(def, referent, null, lvl, BlockType.EXTERNAL_PROC, block);
       }

       /**
        * Execute the given internal procedure block with a default transaction
        * level of <code>TransactionType.SUB</code>.
        *
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(Block block)
       {
          internalProcedure(TransactionType.SUB, block);
       }

       /**
        * Execute the given internal procedure block with the given transaction
        * level.
        *
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(TransactionType lvl, Block block)
       {
          topLevelBlock(null, null, null, lvl, BlockType.INTERNAL_PROC, block);
       }

       /**
        * Execute the given internal procedure block with a default transaction
        * level of <code>TransactionType.SUB</code>.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(String legacyName, Block block)
       {
          internalProcedure(legacyName, TransactionType.SUB, block);
       }

       /**
        * Execute the given internal procedure block with the given transaction
        * level.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(String legacyName, TransactionType lvl, Block block)
       {
          topLevelBlock(null, null, legacyName, lvl, BlockType.INTERNAL_PROC, block);
       }

       /**
        * Execute the given internal procedure block with a default transaction
        * level of <code>TransactionType.SUB</code>.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(Object referent, String legacyName, Block block)
       {
          internalProcedure(referent, legacyName, TransactionType.SUB, block);
       }

       /**
        * Execute the given internal procedure block with the given transaction
        * level.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(Object          referent,
                                            String          legacyName,
                                            TransactionType lvl,
                                            Block           block)
       {
          topLevelBlock(null, referent, legacyName, lvl, BlockType.INTERNAL_PROC, block);
       }

       /**
        * Execute the given internal procedure block with a default transaction
        * level of <code>TransactionType.SUB</code>.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(Class<?> def,
                                            Object referent,
                                            String legacyName,
                                            Block block)
       {
          internalProcedure(def, referent, legacyName, TransactionType.SUB, block);
       }

       /**
        * Execute the given internal procedure block with the given transaction
        * level.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        */
       public static void internalProcedure(Class<?>        def,
                                            Object          referent,
                                            String          legacyName,
                                            TransactionType lvl,
                                            Block           block)
       {
          topLevelBlock(def, referent, legacyName, lvl, BlockType.INTERNAL_PROC, block);
       }

       /**
        * Execute the given trigger block as a SUB-transaction.
        *
        * @param    block
        *           The code to execute.
        */
       public static void trigger(Block block)
       {
          // TODO: check if TransactionType.FULL is not the appropriate type
          topLevelBlock(null, null, null, TransactionType.SUB, BlockType.DATABASETRIGGER, block);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        *
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Class<T> cls, Block block)
       {
          return (T) function(cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level.
        *
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Class<T>        cls,
                                                         TransactionType lvl,
                                                         Block           block)
       {
          return ((T) functionBlock(null, null, null, lvl, block, cls, -1));
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns an extent value.
        *
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<T> cls,
                                                                 int      extent,
                                                                 Block    block)
       {
          return (T[]) extentFunction(cls, extent, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns an extent
        * value.
        *
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<T>        cls,
                                                                 int             extent,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(null, null, null, lvl, block, cls, extent);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns a dynamic extent value.
        *
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<T> cls,
                                                                 Block    block)
       {
          return (T[]) extentFunction(cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns a
        * dynamic extent value.
        *
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<T>        cls,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(null, null, null, lvl, block, cls, 0);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(String legacyName, Class<T> cls, Block block)
       {
          return (T) function(legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(String          legacyName,
                                                         Class<T>        cls,
                                                         TransactionType lvl,
                                                         Block           block)
       {
          return (T) functionBlock(null, null, legacyName, lvl, block, cls, -1);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Object   referent,
                                                         String   legacyName,
                                                         Class<T> cls,
                                                         Block    block)
       {
          return (T) function(referent, legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Object          referent,
                                                         String          legacyName,
                                                         Class<T>        cls,
                                                         TransactionType lvl,
                                                         Block           block)
       {
          return (T) functionBlock(null, referent, legacyName, lvl, block, cls, -1);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Class<?> def,
                                                         Object   referent,
                                                         String   legacyName,
                                                         Class<T> cls,
                                                         Block    block)
       {
          return (T) function(def, referent, legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       public static <T extends BaseDataType> T function(Class<?>        def,
                                                         Object          referent,
                                                         String          legacyName,
                                                         Class<T>        cls,
                                                         TransactionType lvl,
                                                         Block           block)
       {
          return (T) functionBlock(def, referent, legacyName, lvl, block, cls, -1);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns an extent value.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(String   legacyName,
                                                                 Class<T> cls,
                                                                 int      extent,
                                                                 Block    block)
       {
          return (T[]) extentFunction(legacyName, cls, extent, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns an extent
        * value.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(String   legacyName,
                                                                 Class<T>        cls,
                                                                 int             extent,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(null, null, legacyName, lvl, block, cls, extent);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns a dynamic extent value.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(String   legacyName,
                                                                 Class<T> cls,
                                                                 Block    block)
       {
          return (T[]) extentFunction(legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns a
        * dynamic extent value.
        *
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(String          legacyName,
                                                                 Class<T>        cls,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(null, null, legacyName, lvl, block, cls, 0);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns an extent value.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Object   referent,
                                                                 String   legacyName,
                                                                 Class<T> cls,
                                                                 int      extent,
                                                                 Block    block)
       {
          return (T[]) extentFunction(null, referent, legacyName, cls, extent, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns an extent value.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<?> def,
                                                                 Object   referent,
                                                                 String   legacyName,
                                                                 Class<T> cls,
                                                                 int      extent,
                                                                 Block    block)
       {
          return (T[]) extentFunction(def, referent, legacyName, cls, extent, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns an extent
        * value.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    extent
        *           The function's return extent value.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<?>        def,
                                                                 Object          referent,
                                                                 String          legacyName,
                                                                 Class<T>        cls,
                                                                 int             extent,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(def, referent, legacyName, lvl, block, cls, extent);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns a dynamic extent value.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Object   referent,
                                                                 String   legacyName,
                                                                 Class<T> cls,
                                                                 Block    block)
       {
          return (T[]) extentFunction(referent, legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with a default transaction level of
        * <code>TransactionType.SUB</code>, which returns a dynamic extent value.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<?> def,
                                                                 Object   referent,
                                                                 String   legacyName,
                                                                 Class<T> cls,
                                                                 Block    block)
       {
          return (T[]) extentFunction(def, referent, legacyName, cls, TransactionType.SUB, block);
       }

       /**
        * Execute the given function block with the given transaction level, which returns a
        * dynamic extent value.
        *
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Object          referent,
                                                                 String          legacyName,
                                                                 Class<T>        cls,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(null, referent, legacyName, lvl, block, cls, 0);
       }

       /**
        * Execute the given function block with the given transaction level, which returns a
        * dynamic extent value.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    cls
        *           The function's return type.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        *
        * @return   The return value from the block (or its nested blocks).
        */
       public static <T extends BaseDataType> T[] extentFunction(Class<?>        def,
                                                                 Object          referent,
                                                                 String          legacyName,
                                                                 Class<T>        cls,
                                                                 TransactionType lvl,
                                                                 Block           block)
       {
          return (T[]) functionBlock(def, referent, legacyName, lvl, block, cls, 0);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(String label, Block block)
       {
          doBlockWorker(TransactionType.NONE, null, label, null, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(String[] enclosing, String label, Block block)
       {
          doBlockWorker(TransactionType.NONE, enclosing, label, null, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(TransactionType lvl, String label, Block block)
       {
          doBlockWorker(lvl, null, label, null, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(TransactionType lvl,
                                  String[]        enclosing,
                                  String          label,
                                  Block           block)
       {
          doBlockWorker(lvl, enclosing, label, null, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(String label, OnPhrase[] on, Block block)
       {
          doBlockWorker(TransactionType.NONE, null, label, on, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(String[]   enclosing,
                                  String     label,
                                  OnPhrase[] on,
                                  Block      block)
       {
          doBlockWorker(TransactionType.NONE, enclosing, label, on, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(TransactionType lvl,
                                  String          label,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          doBlockWorker(lvl, null, label, on, block);
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration
        * and no default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doBlock(TransactionType lvl,
                                  String[]        enclosing,
                                  String          label,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          doBlockWorker(lvl, enclosing, label, on, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(String label, LogicalOp expr, Block block)
       {
          doLoopWorker(TransactionType.NONE, null, label, null, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(String[] enclosing, String label, LogicalOp expr, Block block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(TransactionType lvl, String label, LogicalOp expr, Block block)
       {
          doLoopWorker(lvl, null, label, null, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(TransactionType lvl,
                                  String[]        enclosing,
                                  String          label,
                                  LogicalOp       expr,
                                  Block           block)
       {
          doLoopWorker(lvl, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(String label, LogicalOp expr, OnPhrase[] on, Block block)
       {
          doLoopWorker(TransactionType.NONE, null, label, null, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(String[]   enclosing,
                                  String     label,
                                  LogicalOp  expr,
                                  OnPhrase[] on,
                                  Block      block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(TransactionType lvl,
                                  String          label,
                                  LogicalOp       expr,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          doLoopWorker(lvl, null, label, null, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression loop with the given configuration
        * and no default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doWhile(TransactionType lvl,
                                  String[]        enclosing,
                                  String          label,
                                  LogicalOp       expr,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          doLoopWorker(lvl, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(String label, ToClause to, Block block)
       {
          doLoopWorker(TransactionType.NONE, null, label, to, null, null, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(String[] enclosing,
                               String   label,
                               ToClause to,
                               Block    block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(TransactionType lvl,
                               String          label,
                               ToClause        to,
                               Block           block)
       {
          doLoopWorker(lvl, null, label, to, null, null, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(TransactionType lvl,
                               String[]        enclosing,
                               String          label,
                               ToClause        to,
                               Block           block)
       {
          doLoopWorker(lvl, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(String     label,
                               ToClause   to,
                               OnPhrase[] on,
                               Block      block)
       {
          doLoopWorker(TransactionType.NONE, null, label, to, null, on, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties. <code>TransactionType.NONE</code> will be
        * used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(String[]   enclosing,
                               String     label,
                               ToClause   to,
                               OnPhrase[] on,
                               Block      block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(TransactionType lvl,
                               String          label,
                               ToClause        to,
                               OnPhrase[]      on,
                               Block           block)
       {
          doLoopWorker(lvl, null, label, to, null, on, block);
       }

       /**
        * Execute a DO TO expression loop with the given configuration
        * and no default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doTo(TransactionType lvl,
                               String[]        enclosing,
                               String          label,
                               ToClause        to,
                               OnPhrase[]      on,
                               Block           block)
       {
          doLoopWorker(lvl, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.NONE</code> will be used and there are no
        * enclosing non-managed blocks. In addition, there are no user-defined
        * properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(String label, ToClause to, LogicalOp expr, Block block)
       {
          doLoopWorker(TransactionType.NONE, null, label, to, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.NONE</code> will be used and there are no
        * user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(String[]  enclosing,
                                    String    label,
                                    ToClause  to,
                                    LogicalOp expr,
                                    Block     block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties and no enclosing non-managed
        * blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(TransactionType lvl,
                                    String          label,
                                    ToClause        to,
                                    LogicalOp       expr,
                                    Block           block)
       {
          doLoopWorker(lvl, null, label, to, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(TransactionType lvl,
                                    String[]        enclosing,
                                    String          label,
                                    ToClause        to,
                                    LogicalOp       expr,
                                    Block           block)
       {
          doLoopWorker(lvl, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.NONE</code> will be used and there are no
        * enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(String     label,
                                    ToClause   to,
                                    LogicalOp  expr,
                                    OnPhrase[] on,
                                    Block      block)
       {
          doLoopWorker(TransactionType.NONE, null, label, to, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.NONE</code> will be used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(String[]   enclosing,
                                    String     label,
                                    ToClause   to,
                                    LogicalOp  expr,
                                    OnPhrase[] on,
                                    Block      block)
       {
          doLoopWorker(TransactionType.NONE, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        * <p>
        * There are no enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(TransactionType lvl,
                                    String          label,
                                    ToClause        to,
                                    LogicalOp       expr,
                                    OnPhrase[]      on,
                                    Block           block)
       {
          doLoopWorker(lvl, null, label, to, expr, on, block);
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void doToWhile(TransactionType lvl,
                                    String[]        enclosing,
                                    String          label,
                                    ToClause        to,
                                    LogicalOp       expr,
                                    OnPhrase[]      on,
                                    Block           block)
       {
          doLoopWorker(lvl, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(String label, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, null, null, null, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(String[] enclosing, String label, Block block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties.  There are no user-defined properties and
        * there are no enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(TransactionType lvl, String label, Block block)
       {
          repeatWorker(lvl, null, label, null, null, null, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties.  There are no user-defined properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(TransactionType lvl,
                                 String[]        enclosing,
                                 String          label,
                                 Block           block)
       {
          repeatWorker(lvl, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used
        * and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(String label, OnPhrase[] on, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, null, null, on, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(String[]   enclosing,
                                 String     label,
                                 OnPhrase[] on,
                                 Block      block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(TransactionType lvl,
                                 String          label,
                                 OnPhrase[]      on,
                                 Block           block)
       {
          repeatWorker(lvl, null, label, null, null, on, block);
       }

       /**
        * Execute a simple REPEAT (infinite loop) with the given configuration
        * and default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeat(TransactionType lvl,
                                 String[]        enclosing,
                                 String          label,
                                 OnPhrase[]      on,
                                 Block           block)
       {
          repeatWorker(lvl, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(String label, LogicalOp expr, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, null, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(String[] enclosing, String label, LogicalOp expr, Block block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(TransactionType lvl, String label, LogicalOp expr, Block block)
       {
          repeatWorker(lvl, null, label, null, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(TransactionType lvl,
                                      String[]        enclosing,
                                      String          label,
                                      LogicalOp       expr,
                                      Block           block)
       {
          repeatWorker(lvl, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(String label, LogicalOp expr, OnPhrase[] on, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, null, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(String[]   enclosing,
                                      String     label,
                                      LogicalOp  expr,
                                      OnPhrase[] on,
                                      Block      block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(TransactionType lvl,
                                      String          label,
                                      LogicalOp       expr,
                                      OnPhrase[]      on,
                                      Block           block)
       {
          repeatWorker(lvl, null, label, null, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression loop with the given configuration
        * and default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatWhile(TransactionType lvl,
                                      String[]        enclosing,
                                      String          label,
                                      LogicalOp       expr,
                                      OnPhrase[]      on,
                                      Block           block)
       {
          repeatWorker(lvl, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(String label, ToClause to, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, to, null, null, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(String[] enclosing,
                                   String   label,
                                   ToClause to,
                                   Block    block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(TransactionType lvl,
                                   String          label,
                                   ToClause        to,
                                   Block           block)
       {
          repeatWorker(lvl, null, label, to, null, null, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(TransactionType lvl,
                                   String[]        enclosing,
                                   String          label,
                                   ToClause        to,
                                   Block           block)
       {
          repeatWorker(lvl, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(String     label,
                                   ToClause   to,
                                   OnPhrase[] on,
                                   Block      block)
       {
          repeatWorker(TransactionType.SUB, null, label, to, null, on, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(String[]   enclosing,
                                   String     label,
                                   ToClause   to,
                                   OnPhrase[] on,
                                   Block      block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(TransactionType lvl,
                                   String          label,
                                   ToClause        to,
                                   OnPhrase[]      on,
                                   Block           block)
       {
          repeatWorker(lvl, null, label, to, null, on, block);
       }

       /**
        * Execute a REPEAT TO expression loop with the given configuration
        * and default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatTo(TransactionType lvl,
                                   String[]        enclosing,
                                   String          label,
                                   ToClause        to,
                                   OnPhrase[]      on,
                                   Block           block)
       {
          repeatWorker(lvl, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks. In addition, there are no user-defined
        * properties.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(String label, ToClause to, LogicalOp expr, Block block)
       {
          repeatWorker(TransactionType.SUB, null, label, to, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * user-defined properties.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(String[]  enclosing,
                                        String    label,
                                        ToClause  to,
                                        LogicalOp expr,
                                        Block     block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties and no enclosing non-managed
        * blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(TransactionType lvl,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        Block           block)
       {
          repeatWorker(lvl, null, label, to, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(TransactionType lvl,
                                        String[]        enclosing,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        Block           block)
       {
          repeatWorker(lvl, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks.
        *
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(String     label,
                                        ToClause   to,
                                        LogicalOp  expr,
                                        OnPhrase[] on,
                                        Block      block)
       {
          repeatWorker(TransactionType.SUB, null, label, to, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(String[]   enclosing,
                                        String     label,
                                        ToClause   to,
                                        LogicalOp  expr,
                                        OnPhrase[] on,
                                        Block      block)
       {
          repeatWorker(TransactionType.SUB, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no enclosing non-managed blocks.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(TransactionType lvl,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          repeatWorker(lvl, null, label, to, expr, on, block);
       }

       /**
        * Execute a REPEAT WHILE expression, REPEAT TO var = val1 to val2 by val3
        * or REPEAT TO WHILE expression loop with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void repeatToWhile(TransactionType lvl,
                                        String[]        enclosing,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          repeatWorker(lvl, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(P2JQuery query, int direction, String label, Block block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, null, null, null, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(P2JQuery query,
                                   int      direction,
                                   String[] enclosing,
                                   String   label,
                                   Block    block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties.  There are no user-defined properties and
        * there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(TransactionType lvl,
                                   P2JQuery        query,
                                   int             direction,
                                   String          label,
                                   Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, null, null, null, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties.  There are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(TransactionType lvl,
                                   P2JQuery        query,
                                   int             direction,
                                   String[]        enclosing,
                                   String          label,
                                   Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used
        * and there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(P2JQuery   query,
                                   int        direction,
                                   String     label,
                                   OnPhrase[] on,
                                   Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, null, null, on, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(P2JQuery   query,
                                   int        direction,
                                   String[]   enclosing,
                                   String     label,
                                   OnPhrase[] on,
                                   Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(TransactionType lvl,
                                   P2JQuery        query,
                                   int             direction,
                                   String          label,
                                   OnPhrase[]      on,
                                   Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, null, null, on, block);
       }

       /**
        * Execute a FOR FIRST or FOR LAST block with the given configuration
        * and default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlock(TransactionType lvl,
                                   P2JQuery        query,
                                   int             direction,
                                   String[]        enclosing,
                                   String          label,
                                   OnPhrase[]      on,
                                   Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(P2JQuery  query,
                                        int       direction,
                                        String    label,
                                        LogicalOp expr,
                                        Block     block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, null, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(P2JQuery query,
                                        int direction,
                                        String[] enclosing,
                                        String label,
                                        LogicalOp expr,
                                        Block block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(TransactionType lvl,
                                        P2JQuery        query,
                                        int             direction,
                                        String          label,
                                        LogicalOp       expr,
                                        Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, null, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and no user-defined or default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(TransactionType lvl,
                                        P2JQuery        query,
                                        int             direction,
                                        String[]        enclosing,
                                        String          label,
                                        LogicalOp       expr,
                                        Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(P2JQuery query,
                                        int direction,
                                        String label,
                                        LogicalOp expr,
                                        OnPhrase[] on,
                                        Block block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, null, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(P2JQuery   query,
                                        int        direction,
                                        String[]   enclosing,
                                        String     label,
                                        LogicalOp  expr,
                                        OnPhrase[] on,
                                        Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(TransactionType lvl,
                                        P2JQuery        query,
                                        int             direction,
                                        String          label,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, null, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block with the given configuration
        * and default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockWhile(TransactionType lvl,
                                        P2JQuery        query,
                                        int             direction,
                                        String[]        enclosing,
                                        String          label,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(P2JQuery query, int direction, String label, ToClause to, Block block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, to, null, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(P2JQuery query,
                                     int      direction,
                                     String[] enclosing,
                                     String   label,
                                     ToClause to,
                                     Block    block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(TransactionType lvl,
                                     P2JQuery        query,
                                     int             direction,
                                     String          label,
                                     ToClause        to,
                                     Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, to, null, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and no user-defined or default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(TransactionType lvl,
                                     P2JQuery        query,
                                     int             direction,
                                     String[]        enclosing,
                                     String          label,
                                     ToClause        to,
                                     Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(P2JQuery   query,
                                     int        direction,
                                     String     label,
                                     ToClause   to,
                                     OnPhrase[] on,
                                     Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, (String[]) null, label, to, null, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(P2JQuery   query,
                                     int        direction,
                                     String[]   enclosing,
                                     String     label,
                                     ToClause   to,
                                     OnPhrase[] on,
                                     Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(TransactionType lvl,
                                     P2JQuery        query,
                                     int             direction,
                                     String          label,
                                     ToClause        to,
                                     OnPhrase[]      on,
                                     Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, to, null, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST TO block with the given configuration
        * and default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockTo(TransactionType lvl,
                                     P2JQuery        query,
                                     int             direction,
                                     String[]        enclosing,
                                     String          label,
                                     ToClause        to,
                                     OnPhrase[]      on,
                                     Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks. In addition, there are no user-defined
        * properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(P2JQuery  query,
                                          int       direction,
                                          String    label,
                                          ToClause  to,
                                          LogicalOp expr,
                                          Block     block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, null, label, to, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(P2JQuery  query,
                                          int       direction,
                                          String[]  enclosing,
                                          String    label,
                                          ToClause  to,
                                          LogicalOp expr,
                                          Block     block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties and no enclosing non-managed
        * blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(TransactionType lvl,
                                          P2JQuery        query,
                                          int             direction,
                                          String          label,
                                          ToClause        to,
                                          LogicalOp       expr,
                                          Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, to, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(TransactionType lvl,
                                          P2JQuery        query,
                                          int             direction,
                                          String[]        enclosing,
                                          String          label,
                                          ToClause        to,
                                          LogicalOp       expr,
                                          Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(P2JQuery   query,
                                          int        direction,
                                          String     label,
                                          ToClause   to,
                                          LogicalOp  expr,
                                          OnPhrase[] on,
                                          Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, (String[]) null, label, to, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(P2JQuery   query,
                                          int        direction,
                                          String[]   enclosing,
                                          String     label,
                                          ToClause   to,
                                          LogicalOp  expr,
                                          OnPhrase[] on,
                                          Block      block)
       {
          forBlockWorker(TransactionType.SUB, query, direction, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(TransactionType lvl,
                                          P2JQuery        query,
                                          int             direction,
                                          String          label,
                                          ToClause        to,
                                          LogicalOp       expr,
                                          OnPhrase[]      on,
                                          Block           block)
       {
          forBlockWorker(lvl, query, direction, null, label, to, expr, on, block);
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forBlockToWhile(TransactionType lvl,
                                          P2JQuery        query,
                                          int             direction,
                                          String[]        enclosing,
                                          String          label,
                                          ToClause        to,
                                          LogicalOp       expr,
                                          OnPhrase[]      on,
                                          Block           block)
       {
          forBlockWorker(lvl, query, direction, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forBlock.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(P2JQuery query, String label, Block block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, null, null, null, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(P2JQuery query, String[] enclosing, String label, Block block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties.  There are no user-defined properties and
        * there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(TransactionType lvl, P2JQuery query, String label, Block block)
       {
          forEachWorker(lvl, query, null, label, null, null, null, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties.  There are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(TransactionType lvl,
                                  P2JQuery        query,
                                  String[]        enclosing,
                                  String          label,
                                  Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, null, null, null, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used
        * and there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(P2JQuery query, String label, OnPhrase[] on, Block block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, null, null, on, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties.  <code>TransactionType.SUB</code> will be used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(P2JQuery   query,
                                  String[]   enclosing,
                                  String     label,
                                  OnPhrase[] on,
                                  Block      block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(TransactionType lvl,
                                  P2JQuery        query,
                                  String          label,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          forEachWorker(lvl, query, null, label, null, null, on, block);
       }

       /**
        * Execute a FOR EACH loop with the given configuration
        * and default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEach(TransactionType lvl,
                                  P2JQuery        query,
                                  String[]        enclosing,
                                  String          label,
                                  OnPhrase[]      on,
                                  Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, null, null, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(P2JQuery query, String label, LogicalOp expr, Block block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, null, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(P2JQuery query,
                                       String[] enclosing,
                                       String label,
                                       LogicalOp expr,
                                       Block block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(TransactionType lvl,
                                       P2JQuery        query,
                                       String          label,
                                       LogicalOp       expr,
                                       Block           block)
       {
          forEachWorker(lvl, query, null, label, null, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and no user-defined or default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(TransactionType lvl,
                                       P2JQuery        query,
                                       String[]        enclosing,
                                       String          label,
                                       LogicalOp       expr,
                                       Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, null, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(P2JQuery query, String label, LogicalOp expr, OnPhrase[] on, Block block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, null, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(P2JQuery   query,
                                       String[]   enclosing,
                                       String     label,
                                       LogicalOp  expr,
                                       OnPhrase[] on,
                                       Block      block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(TransactionType lvl,
                                       P2JQuery        query,
                                       String          label,
                                       LogicalOp       expr,
                                       OnPhrase[]      on,
                                       Block           block)
       {
          forEachWorker(lvl, query, null, label, null, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block with the given configuration
        * and default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    expr
        *           The WHILE clause that defines the loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachWhile(TransactionType lvl,
                                       P2JQuery        query,
                                       String[]        enclosing,
                                       String          label,
                                       LogicalOp       expr,
                                       OnPhrase[]      on,
                                       Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, null, expr, on, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks. In addition, there
        * are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(P2JQuery query,
                                    String   label,
                                    ToClause to,
                                    Block    block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, to, null, null, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(P2JQuery query,
                                    String[] enclosing,
                                    String   label,
                                    ToClause to,
                                    Block    block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and no user-defined or default properties. In addition, there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(TransactionType lvl,
                                    P2JQuery        query,
                                    String          label,
                                    ToClause        to,
                                    Block           block)
       {
          forEachWorker(lvl, query, null, label, to, null, null, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and no user-defined or default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(TransactionType lvl,
                                    P2JQuery        query,
                                    String[]        enclosing,
                                    String          label,
                                    ToClause        to,
                                    Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, to, null, null, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used and there are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(P2JQuery   query,
                                    String     label,
                                    ToClause   to,
                                    OnPhrase[] on,
                                    Block      block)
       {
          forEachWorker(TransactionType.SUB, query, (String[]) null, label, to, null, on, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties. <code>TransactionType.SUB</code> will be
        * used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(P2JQuery   query,
                                    String[]   enclosing,
                                    String     label,
                                    ToClause   to,
                                    OnPhrase[] on,
                                    Block      block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties. In this case, there are no enclosing
        * non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(TransactionType lvl,
                                    P2JQuery        query,
                                    String          label,
                                    ToClause        to,
                                    OnPhrase[]      on,
                                    Block           block)
       {
          forEachWorker(lvl, query, null, label, to, null, on, block);
       }

       /**
        * Execute a FOR EACH TO block with the given configuration
        * and default properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachTo(TransactionType lvl,
                                    P2JQuery        query,
                                    String[]        enclosing,
                                    String          label,
                                    ToClause        to,
                                    OnPhrase[]      on,
                                    Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, to, null, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks. In addition, there are no user-defined
        * properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(P2JQuery query, String label, ToClause to, LogicalOp expr, Block block)
       {
          forEachWorker(TransactionType.SUB, query, null, label, to, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(P2JQuery  query,
                                         String[]  enclosing,
                                         String    label,
                                         ToClause  to,
                                         LogicalOp expr,
                                         Block     block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties and no enclosing non-managed
        * blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(TransactionType lvl,
                                         P2JQuery        query,
                                         String          label,
                                         ToClause        to,
                                         LogicalOp       expr,
                                         Block           block)
       {
          forEachWorker(lvl, query, null, label, to, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no user-defined properties.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(TransactionType lvl,
                                         P2JQuery        query,
                                         String[]        enclosing,
                                         String          label,
                                         ToClause        to,
                                         LogicalOp       expr,
                                         Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, to, expr, null, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used and there are no
        * enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(P2JQuery   query,
                                         String     label,
                                         ToClause   to,
                                         LogicalOp  expr,
                                         OnPhrase[] on,
                                         Block      block)
       {
          forEachWorker(TransactionType.SUB, query, (String[]) null, label, to, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties. At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * <code>TransactionType.SUB</code> will be used.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(P2JQuery   query,
                                         String[]   enclosing,
                                         String     label,
                                         ToClause   to,
                                         LogicalOp  expr,
                                         OnPhrase[] on,
                                         Block      block)
       {
          forEachWorker(TransactionType.SUB, query, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * There are no enclosing non-managed blocks.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(TransactionType lvl,
                                         P2JQuery        query,
                                         String          label,
                                         ToClause        to,
                                         LogicalOp       expr,
                                         OnPhrase[]      on,
                                         Block           block)
       {
          forEachWorker(lvl, query, null, label, to, expr, on, block);
       }

       /**
        * Execute a FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * default properties.  At least one of the to clause or while expression
        * must be passed and it is valid to have both passed in which case both
        * of the conditions are tested with a logical AND.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself.  This
        * means that the caller is responsible for all query processing. The
        * record retrieval must be done on the first line of code in the block
        * to duplicate the Progress behavior. Note that this is required to
        * handle all error cases and 4GL conditions properly.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       public static void forEachToWhile(TransactionType lvl,
                                         P2JQuery        query,
                                         String[]        enclosing,
                                         String          label,
                                         ToClause        to,
                                         LogicalOp       expr,
                                         OnPhrase[]      on,
                                         Block           block)
       {
          forEachWorker(lvl, query, enclosing, label, to, expr, on, block);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditingUnlessHidden(CommonFrame    frame,
                                                       FrameElement[] widgets,
                                                       String         label,
                                                       Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, null,  null, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditingUnlessHidden(CommonFrame    frame,
                                                       FrameElement[] widgets,
                                                       String[]       enclosing,
                                                       String         label,
                                                       Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }
          editingBlock(frame, dataChanged, null, enclosing, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditingUnlessHidden(CommonFrame    frame,
                                                       FrameElement[] widgets,
                                                       EventList      goOn,
                                                       String         label,
                                                       Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, null, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditingUnlessHidden(CommonFrame    frame,
                                                       FrameElement[] widgets,
                                                       EventList      goOn,
                                                       String[]       enclosing,
                                                       String         label,
                                                       Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, enclosing, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditingUnlessHidden(CommonFrame    frame,
                                                 FrameElement[] widgets,
                                                 String         label,
                                                 Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, null, null, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditingUnlessHidden(CommonFrame    frame,
                                                 FrameElement[] widgets,
                                                 String[]       enclosing,
                                                 String         label,
                                                 Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, null, enclosing, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditingUnlessHidden(CommonFrame    frame,
                                                 FrameElement[] widgets,
                                                 EventList      goOn,
                                                 String         label,
                                                 Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, null, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditingUnlessHidden(CommonFrame    frame,
                                                 FrameElement[] widgets,
                                                 EventList      goOn,
                                                 String[]       enclosing,
                                                 String         label,
                                                 Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, enclosing, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditingUnlessHidden(CommonFrame    frame,
                                                    FrameElement[] widgets,
                                                    String         label,
                                                    Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, null, null, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditingUnlessHidden(CommonFrame    frame,
                                                    FrameElement[] widgets,
                                                    String[]       enclosing,
                                                    String         label,
                                                    Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, null, enclosing, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditingUnlessHidden(CommonFrame    frame,
                                                    FrameElement[] widgets,
                                                    EventList      goOn,
                                                    String         label,
                                                    Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, null, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditingUnlessHidden(CommonFrame    frame,
                                                    FrameElement[] widgets,
                                                    EventList      goOn,
                                                    String[]       enclosing,
                                                    String         label,
                                                    Block          block)
       {
          FrameElement[] dataChanged = GenericFrame.removeHiddenWidgets(widgets);

          if (dataChanged == null || dataChanged.length == 0)
          {
             return;
          }

          editingBlock(frame, dataChanged, goOn, enclosing, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditing(CommonFrame    frame,
                                           FrameElement[] widgets,
                                           String         label,
                                           Block          block)
       {
          editingBlock(frame, widgets, null,  null, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditing(CommonFrame    frame,
                                           FrameElement[] widgets,
                                           String[]       enclosing,
                                           String         label,
                                           Block          block)
       {
          editingBlock(frame, widgets, null, enclosing, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditing(CommonFrame    frame,
                                           FrameElement[] widgets,
                                           EventList      goOn,
                                           String         label,
                                           Block          block)
       {
          editingBlock(frame, widgets, goOn, null, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>PROMPT-FOR</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void promptForEditing(CommonFrame    frame,
                                           FrameElement[] widgets,
                                           EventList      goOn,
                                           String[]       enclosing,
                                           String         label,
                                           Block          block)
       {
          editingBlock(frame, widgets, goOn, enclosing, label, block, CommonFrame.PROMPT_FOR);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditing(CommonFrame    frame,
                                     FrameElement[] widgets,
                                     String         label,
                                     Block          block)
       {
          editingBlock(frame, widgets, null, null, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditing(CommonFrame    frame,
                                     FrameElement[] widgets,
                                     String[]       enclosing,
                                     String         label,
                                     Block          block)
       {
          editingBlock(frame, widgets, null, enclosing, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditing(CommonFrame    frame,
                                     FrameElement[] widgets,
                                     EventList      goOn,
                                     String         label,
                                     Block          block)
       {
          editingBlock(frame, widgets, goOn, null, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>SET</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void setEditing(CommonFrame    frame,
                                     FrameElement[] widgets,
                                     EventList      goOn,
                                     String[]       enclosing,
                                     String         label,
                                     Block          block)
       {
          editingBlock(frame, widgets, goOn, enclosing, label, block, CommonFrame.SET);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditing(CommonFrame    frame,
                                        FrameElement[] widgets,
                                        String         label,
                                        Block          block)
       {
          editingBlock(frame, widgets, null, null, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditing(CommonFrame    frame,
                                        FrameElement[] widgets,
                                        String[]       enclosing,
                                        String         label,
                                        Block          block)
       {
          editingBlock(frame, widgets, null, enclosing, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditing(CommonFrame    frame,
                                        FrameElement[] widgets,
                                        EventList      goOn,
                                        String         label,
                                        Block          block)
       {
          editingBlock(frame, widgets, goOn, null, label, block, CommonFrame.UPDATE);
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        */
       public static void updateEditing(CommonFrame    frame,
                                        FrameElement[] widgets,
                                        EventList      goOn,
                                        String[]       enclosing,
                                        String         label,
                                        Block          block)
       {
          editingBlock(frame, widgets, goOn, enclosing, label, block, CommonFrame.UPDATE);
       }

       /**
        * Break out of the nearest enclosing block.
        *
        * @throws   LeaveUnwindException
        */
       public static void leave()
       throws LeaveUnwindException
       {
          leave("");
       }

       /**
        * Break out of the block associated with the given label.  This will
        * unwind the stack until the proper block has been reached.  At that
        * point the block will be left using the Java "break" statement.
        *
        * @param    label
        *           The name of the block to be left.
        *
        * @throws   LeaveUnwindException
        */
       public static void leave(String label)
       throws LeaveUnwindException
       {
          leave(work.obtain(), label);
       }

       /**
        * Detect if there is a pending leave for the block named by the given
        * label. If so, this deferred leave flag will be cleared and
        * <code>true</code> will be returned.  The caller is responsible for
        * ensuring that the leave request is fully granted as no further state
        * will be available for subsequent processing.
        *
        * @param    label
        *           The name of the block to be checked against the deferred
        *           leave block name.
        *
        * @return   <code>true</code> if there is a pending deferred leave and
        *           the name of the block to be left is the same as the given
        *           label. If the pending deferred block name is the "" (empty
        *           string), that is the equivalent of matching "any block" and
        *           so the first call to this method after that is set will cause
        *           a <code>true</code> to be returned.
        */
       public static boolean deferredLeave(String label)
       {
          return deferredLeaveWorker(null, label);
       }

       /**
        * Continue (iterate) the nearest enclosing block.
        *
        * @throws   NextUnwindException
        */
       public static void next()
       throws NextUnwindException
       {
          next("");
       }

       /**
        * Continue (iterate) the block associated with the given label.  This will
        * unwind the stack until the proper block has been reached.  At that
        * point the block will be iterated using the Java "continue" statement.
        *
        * @param    label
        *           The name of the block to be iterated.
        *
        * @throws   NextUnwindException
        */
       public static void next(String label)
       throws NextUnwindException
       {
          next(work.obtain(), label);
       }

       /**
        * Detect if there is a pending next for the block named by the given
        * label. If so, this deferred next flag will be cleared and
        * <code>true</code> will be returned.  The caller is responsible for
        * ensuring that the next request is fully granted as no further state
        * will be available for subsequent processing.
        *
        * @param    label
        *           The name of the block to be checked against the deferred
        *           next block name.
        *
        * @return   <code>true</code> if there is a pending deferred next and
        *           the name of the block to be iterated is the same as the given
        *           label. If the pending deferred block name is the "" (empty
        *           string), that is the equivalent of matching "any block" and
        *           so the first call to this method after that is set will cause
        *           a <code>true</code> to be returned.
        */
       public static boolean deferredNext(String label)
       {
          return deferredNextWorker(null, label);
       }

       /**
        * Raise the STOP condition and cause control to be transferred to the
        * nearest enclosing block that handles the associated condition.
        *
        * @throws   StopConditionException
        */
       public static void stop()
       throws StopConditionException
       {
          String msg = "Explicit STOP.";
          ErrorManager.handleStopException(msg);
       }

       /**
        * Raise the QUIT condition and cause control to be transferred to the
        * nearest enclosing block that handles the associated condition.
        *
        * @throws  QuitConditionException
        */
       public static void quit()
       throws QuitConditionException
       {
          throw new QuitConditionException("Explicit QUIT.");
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the default
        * <code>RETURN-VALUE</code> to "" (empty string) for internal/external
        * procedures and triggers. Leaves <code>unknown value</code> as the
        * default return from a user-defined function.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal()
       throws ReturnUnwindException
       {
          returnWorker(null, null, ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(WrappedResource val)
       throws ReturnUnwindException
       {
          returnNormal(new handle(val));
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(Stream val)
       throws ReturnUnwindException
       {
          returnNormal(new handle(val));
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(BaseDataType val)
       throws ReturnUnwindException
       {
          returnWorker(null, val, ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnExtentNormal(BaseDataType[] val)
       throws ReturnUnwindException
       {
          returnWorker(null, val, ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(String val)
       throws ReturnUnwindException
       {
          returnWorker(new character(val), ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(int val)
       throws ReturnUnwindException
       {
          returnWorker(new integer(val), ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(long val)
       throws ReturnUnwindException
       {
          returnWorker(new int64(val), ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(double val)
       throws ReturnUnwindException
       {
          returnWorker(new decimal(val), ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnNormal(boolean val)
       throws ReturnUnwindException
       {
          returnWorker(logical.of(val), ReturnType.NORMAL);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the default
        * <code>RETURN-VALUE</code> to "" (empty string) for internal/external
        * procedures and triggers. Leaves <code>unknown value</code> as the
        * default return from a user-defined function.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue()
       throws ReturnUnwindException
       {
          returnWorker(null, null, ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(WrappedResource val)
       throws ReturnUnwindException
       {
          returnWorker(null, new handle(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(Stream val)
       throws ReturnUnwindException
       {
          returnWorker(null, new handle(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(BaseDataType val)
       throws ReturnUnwindException
       {
          returnWorker(null, val, ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeExtentReturnValue(BaseDataType[] val)
       throws ReturnUnwindException
       {
          returnWorker(null, val, ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the
        * <code>RETURN-VALUE</code> to the given <code>character</code> value for
        * internal/external procedures and triggers. Saves the given value as the
        * return value for a user-defined function.  If <code>val</code> is
        * <code>null</code>, then <code>RETURN-VALUE</code> will be set to the
        * "" (empty string) for internal/external procedures and triggers. If
        * <code>val</code> is <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(String val)
       throws ReturnUnwindException
       {
          returnWorker(null, new character(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(int val)
       throws ReturnUnwindException
       {
          returnWorker(null, new integer(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(long val)
       throws ReturnUnwindException
       {
          returnWorker(null, new int64(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(double val)
       throws ReturnUnwindException
       {
          returnWorker(null, new decimal(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. This should not be
        * used for internal/external procedures and triggers, since the
        * <code>RETURN-VALUE</code> can only be set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void storeReturnValue(boolean val)
       throws ReturnUnwindException
       {
          returnWorker(null, logical.of(val), ReturnType.STORE);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the default
        * <code>RETURN-VALUE</code> to "" (empty string) for internal/external
        * procedures and triggers. Leaves <code>unknown value</code> as the
        * default return from a user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @throws   ReturnUnwindException
        */
       public static void returnConsume()
       throws ReturnUnwindException
       {
          returnWorker(null, null, ReturnType.CONSUME);
       }

       /**
        * Return from the nearest enclosing top-level block, consuming any pending
        * event processing. Sets the <code>RETURN-VALUE</code> to the given value
        * for internal/external procedures and triggers.  Should not be called
        * for a user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnConsume(character val)
       throws ReturnUnwindException
       {
          returnWorker(val, ReturnType.CONSUME);
       }

       /**
        * Return from the nearest enclosing top-level block, consuming any pending
        * event processing. Sets the <code>RETURN-VALUE</code> to the given value
        * for internal/external procedures and triggers. Sets the given value as
        * the return value for a user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void returnConsume(String val)
       throws ReturnUnwindException
       {
          returnWorker(new character(val), ReturnType.CONSUME);
       }

       /**
        * Return from the nearest enclosing top-level block. Sets the default
        * <code>RETURN-VALUE</code> to "" (empty string) for internal/external
        * procedures and triggers. Leaves <code>unknown value</code> as the
        * default return from a user-defined function.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void returnError()
       throws ReturnUnwindException,
              ErrorConditionException
       {
          returnWorker(null, null, ReturnType.ERROR);
       }

       /**
        * Return from the nearest enclosing top-level block. If the given value
        * is <code>null</code>, this sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * It leaves <code>unknown value</code> as the default return from a
        * user-defined function.  If the value is not <code>null</code>, then
        * that value (if it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void returnError(character val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          returnWorker(val, ReturnType.ERROR);
       }

       /**
        * Return from the nearest enclosing top-level block. If the given value
        * is <code>null</code>, this sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * It leaves <code>unknown value</code> as the default return from a
        * user-defined function.  If the value is not <code>null</code>, then
        * that value will be set as the <code>RETURN-VALUE</code> for internal/
        * external procedures and triggers. If not <code>null</code>, the value
        * will be returned as the function return value for user-defined
        * functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void returnError(String val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          returnWorker(new character(val), ReturnType.ERROR);
       }

       /**
        * Return from the nearest enclosing top-level block by throwing the specified legacy error.
        *
        * @param    error
        *           The error object.
        *
        * @throws   LegacyErrorException
        */
       public static void returnError(object<? extends LegacyError> error)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          if (!error._isValid() || !LegacyError.class.isAssignableFrom(error.ref.getClass()))
          {
             ErrorManager.recordOrThrowError(14477,
                                             "RETURN ERROR statement failed with an invalid error object",
                                             false, false);
             return;
          }

          WorkArea wa = work.get();
          markReturnError(wa);

          setReturnValue(wa, error.ref);

          LegacyErrorException lex = new LegacyErrorException(error, true);
          lex.setExplicit(true);

          if (mustThrowLegacyError(wa, error.ref.getClass()))
          {
             throw lex;
          }
          else
          {
             wa.tm.triggerErrorInCaller(lex);
          }
       }

       /**
        * Execute the default block associated with a <code>CATCH</code> statement.
        *
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void catchBlock(String label, Block block)
       {
          catchBlock(TransactionType.NONE, label, block);
       }

       /**
        * Execute the default block associated with a <code>CATCH</code> statement.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    block
        *           The code to execute.
        */
       public static void catchBlock(TransactionType lvl, String label, Block block)
       {
          String[] enclosing = null;
          block.pre();

          BlockType blockType = BlockType.CATCH;

          int ttype = convertTransType(lvl, blockType);

          OnPhrase[] defOn = new OnPhrase[1];
          defOn[0] = new OnPhrase(Condition.ERROR, Action.THROW, label);

          WorkArea wa = work.obtain();
          int props = decodeConditions(null, defOn);

          wa.tm.pushScope(label, ttype, props, false, false, false, false, blockType);

          try
          {
             // give the block a chance to initialize its state and don't
             // repeat that during retry
             block.init();
             wa.tm.blockSetup();

             blockLabel:
             try
             {
                processBody(wa, block, null, defOn);
             }

             catch (LegacyErrorException lex)
             {
                processLegacyException(wa, lex);
             }

             catch (ConditionException ce)
             {
                wa.tm.notifyCondition(ce);

                switch (processCondition(wa, null, defOn, ce, enclosing, "catchBlock"))
                {
                   // note that this is not an iterating block so a leave or
                   // next targeted at this block must always act the same
                   case BREAK:
                   case CONTINUE:
                      break blockLabel;
                   default:
                      break;
                }
             }

             catch (RetryUnwindException rue)
             {
                wa.tm.honorRetry(rue);
             }

             catch (LeaveUnwindException lue)
             {
                if (testLeave(wa, enclosing, "catchBlock") == Disposition.BREAK)
                {
                   // the LEAVE targeted this block or an enclosing
                   // non-managed block
                   break blockLabel;
                }

                // the LEAVE must be referencing an enclosing block which IS
                // known to the block manager OR to one of the other enclosing
                // managed blocks, so keep unwinding the stack
                throw lue;
             }

             catch (NextUnwindException nue)
             {
                if (testNext(wa, enclosing, "catchBlock") == Disposition.BREAK)
                {
                   // the NEXT can't be targeted at this block BUT it can be
                   // targeted at an enclosing non-managed block
                   break blockLabel;
                }

                // the NEXT must be referencing an enclosing block which IS
                // known to the block manager OR to one of the other enclosing
                // managed blocks, so keep unwinding the stack
                throw nue;
             }

             catch (ReturnUnwindException rue)
             {
                // RETURN can't be targeted at a DO block so keep unwinding
                throw rue;
             }

             catch (Throwable thr)
             {
                wa.tm.abnormalEnd(thr);
             }
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * The CATCH statement.  This API must be called from the Block's init method, and it will
        * register a listener for the specified legacy error.
        * <p>
        * The catch order is the order of this API registration calls.
        *
        * @param    type
        *           The CATCH's error type.
        * @param    catchBlock
        *           The code to be executed for this error.
        */
       public static <T extends LegacyError> void catchError(Class<T>            type,
                                                             Consumer<object<T>> catchBlock)
       {
          registerCatchBlock(type, catchBlock);
       }

       /**
        * The CATCH statement.  This API must be called from the Block's init method, and it will
        * register a listener for the specified STOP condition.
        * <p>
        * The catch order is the order of this API registration calls.
        *
        * @param    type
        *           The CATCH's stop error type.
        * @param    catchBlock
        *           The code to be executed for this error.
        */
       public static <T extends Stop> void catchStop(Class<T>            type,
                                                     Consumer<object<T>> catchBlock)
       {
          registerCatchBlock(type, catchBlock);
       }

       /**
        * Execute the given catch block as if it was a simple DO block.
        *
        * @param    body
        *           The catch block to execute.
        */
       public static void processCatch(Body body)
       {
          doBlock("_catch_block_", new Block(body));
       }

       /**
        * Trigger a rollback of the current block and then throw a legacy condition.
        *
        * @param    error
        *           The legacy error to throw.
        */
       public static void undoThrowTopLevel(object<? extends LegacyError> error)
       {
          if (!error._isValid())
          {
             String[] texts =
             {
                "You can only use a valid object reference in an UNDO, THROW or RETURN ERROR " +
                "statement and it must be a class that implements Progress.Lang.Error",
                "THROW statement failed"
             };
             int[] nums = {14117, 14456};

             ErrorManager.recordOrThrowError(nums, texts, false, false);
             return;
          }

          WorkArea wa = work.get();

          BlockDefinition blk = wa.tm.getBlock();
          if (blk.type == BlockType.CATCH)
          {
             // UNDO, THROW in a CATCH for a top-level block is emitted as 'undoThrowTopLevel'.
             // but the behavior must be undoThrow.
             undoThrow(error);
             return;
          }

          wa.tm.rollbackTopLevel();

          boolean fromReturn = setReturnValue(wa, error.ref);
          LegacyErrorException lex = new LegacyErrorException(error, fromReturn);
          lex.setExplicit(true);

          // only RETURN ERROR is raised on the caller's side for an appserver call.
          if (mustManageLegacyError(wa) && !(AppServerManager.isRemote() && !fromReturn))
          {
             wa.tm.triggerErrorInCaller(lex);
          }

          displayErrorMessages(wa.tm, lex.getErrorRef(), false, false);

          throw lex;
       }

       /**
        * Trigger a rollback of the current block and then throw a legacy STOP condition.
        *
        * @param    stopError
        *           The legacy STOP error to throw.
        */
       public static void undoThrowStopTopLevel(object<? extends Stop> stopError)
       {
          if (!stopError._isValid())
          {
             String[] texts =
             {
                "You can only use a valid object reference in an UNDO, THROW or RETURN" +
                "statement and it must be a class that implements Progress.Lang.Stop",
                "THROW statement failed"
             };
             int[] nums = {14117, 14456};

             ErrorManager.recordOrThrowError(nums, texts, false, false);
             return;
          }

          WorkArea wa = work.get();

          BlockDefinition blk = wa.tm.getBlock();
          if (blk.type == BlockType.CATCH)
          {
             // UNDO, THROW in a CATCH for a top-level block is emitted as 'undoThrowStopTopLevel'.
             // but the behavior must be undoThrow.
             undoThrowStop(stopError);
             return;
          }

          wa.tm.rollbackTopLevel();
          ErrorManager.handleStopException(stopError);
       }

       /**
        * Trigger a rollback of the current block and then throw a legacy condition.
        *
        * @param    error
        *           The legacy error to throw.
        */
       public static void undoThrow(object<? extends LegacyError> error)
       {
          if (!error._isValid())
          {
             String[] texts =
             {
                "You can only use a valid object reference in an UNDO, THROW or RETURN ERROR " +
                "statement and it must be a class that implements Progress.Lang.Error",
                "THROW statement failed"
             };
             int[] nums = {14117, 14456};

             ErrorManager.recordOrThrowError(nums, texts, false, false);
             return;
          }

          WorkArea wa = work.obtain();

          // TODO: any other processing?
          setReturnValue(wa, error.ref);

          if (!ErrorManager.hasLegacyError())
          {
             displayErrorMessages(wa.tm, error.ref, false, true);
          }

          LegacyErrorException lex = new LegacyErrorException(error);
          lex.setExplicit(true);
          throw lex;
       }

       /**
        * Trigger a rollback of the current block and then throw a legacy STOP condition.
        *
        * @param    stopError
        *           The legacy STOP error to throw.
        */
       public static void undoThrowStop(object<? extends Stop> stopError)
       {
          if (!stopError._isValid())
          {
             String[] texts =
             {
                "You can only use a valid object reference in an UNDO, THROW" +
                "statement and it must be a class that implements Progress.Lang.Stop",
                "THROW statement failed"
             };
             int[] nums = {14117, 14456};

             ErrorManager.recordOrThrowError(nums, texts, false, false);
             return;
          }

          ErrorManager.handleStopException(stopError);
       }

       /**
        * Trigger a rollback of the current block and then leave that block.
        *
        * @throws   LeaveUnwindException
        */
       public static void undoLeave()
       throws LeaveUnwindException
       {
          undoLeave(null, "");
       }

       /**
        * Trigger a rollback of the given block and then leave that block.
        *
        * @param    label
        *           The name of the block that is the target of the undo and
        *           leave operations.
        *
        * @throws   LeaveUnwindException
        */
       public static void undoLeave(String label)
       throws LeaveUnwindException
       {
          undoLeave(label, label);
       }

       /**
        * Trigger a rollback of the given block and then leave that block or a
        * more enclosing block.
        * <p>
        * If the current block is a variant of a FOR block, then the buffers
        * associated with the block's query must not change the referenced
        * record.
        *
        * @param    undo
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    leave
        *           The name of the block that is the target of the leave
        *           operation.
        *
        * @throws   LeaveUnwindException
        */
       public static void undoLeave(String undo, String leave)
       throws LeaveUnwindException
       {
          WorkArea wa = work.obtain();

          BlockType blk = wa.tm.getBlockType();

          boolean forBlock = blk == BlockType.FOR_BLOCK          ||
                             blk == BlockType.FOR_BLOCK_WHILE    ||
                             blk == BlockType.FOR_BLOCK_TO       ||
                             blk == BlockType.FOR_BLOCK_TO_WHILE ||
                             blk == BlockType.FOR_LOOP           ||
                             blk == BlockType.FOR_LOOP_WHILE     ||
                             blk == BlockType.FOR_LOOP_TO        ||
                             blk == BlockType.FOR_LOOP_TO_WHILE;

          try
          {
             if (forBlock)
             {
                wa.tm.processOffEndListeners(true);
             }

             wa.tm.rollback(undo);
             leave(wa, leave);
          }
          finally
          {
             if (forBlock)
             {
                wa.tm.processOffEndListeners(false);
             }
          }
       }

       /**
        * Trigger a rollback of the current block and then iterate that block.
        * <p>
        * Infinite loop protection may convert the NEXT action into a LEAVE
        * depending on runtime state.
        *
        * @throws   NextUnwindException
        */
       public static void undoNext()
       throws NextUnwindException
       {
          undoNext(null, "");
       }

       /**
        * Trigger a rollback of the given block and then iterate that block.
        * <p>
        * Infinite loop protection may convert the NEXT action into a LEAVE
        * depending on runtime state.
        *
        * @param    label
        *           The name of the block that is the target of the undo and
        *           next operations.
        *
        * @throws   NextUnwindException
        */
       public static void undoNext(String label)
       throws NextUnwindException
       {
          undoNext(label, label);
       }

       /**
        * Trigger a rollback of the given block and then iterate that block or
        * a more enclosing block.
        * <p>
        * Infinite loop protection may convert the NEXT action into a LEAVE
        * depending on runtime state.
        *
        * @param    undo
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    next
        *           The name of the block that is the target of the next
        *           operation.
        *
        * @throws   NextUnwindException
        */
       public static void undoNext(String undo, String next)
       throws NextUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(undo);

          if (wa.tm.honorNext(next))
          {
             next(wa, next);
          }
          else
          {
             leave(wa, next);
          }
       }

       /**
        * Trigger a rollback of the current block and then retry that block.
        *
        * @throws   RetryUnwindException
        */
       public static void undoRetry()
       throws RetryUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          wa.tm.forceRetry(null);
       }

       /**
        * Trigger a rollback of the given block and then retry that block.
        *
        * @param    label
        *           The name of the block that is the target of the undo and
        *           retry operations.
        *
        * @throws   RetryUnwindException
        */
       public static void undoRetry(String label)
       throws RetryUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          wa.tm.forceRetry(label);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * retry that block.
        *
        * @throws   RetryUnwindException
        */
       public static void undoRetryTopLevel()
       throws RetryUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          wa.tm.forceRetry(null);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code> to
        * "" (empty string) for internal/external procedures and triggers. Leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal()
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, null, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback and then return from the nearest enclosing top-level
        * block. Sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. Leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel()
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, null, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code> to
        * "" (empty string) for internal/external procedures and triggers. Leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, null, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(BaseDataType val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, val, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * return from that block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel(BaseDataType val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, val, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label, BaseDataType val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, val, ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label, String val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, new character(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * return from that block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return or <code>null</code>.  For procedures
        *           or triggers, this must be a <code>character</code> value.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel(String val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, new character(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(int val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, new integer(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * return from that block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel(int val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, new integer(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label, int val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, new integer(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(double val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, new decimal(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * return from that block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel(double val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, new decimal(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label, double val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, new decimal(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(boolean val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, logical.of(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the nearest enclosing top-level block and then
        * return from that block. Sets the <code>RETURN-VALUE</code> to the
        * given <code>character</code> value for internal/external procedures and
        * triggers. Saves the given value as the return value for a user-defined
        * function.  If <code>val</code> is <code>null</code>, then
        * <code>RETURN-VALUE</code> will be set to the "" (empty string) for
        * internal/external procedures and triggers. If <code>val</code> is
        * <code>null</code> for a user-defined function,
        * <code>unknown value</code> will be the default return.
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormalTopLevel(boolean val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, logical.of(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. This should not be used for internal/external
        * procedures and triggers, since the <code>RETURN-VALUE</code> can only be
        * set to a character expression.
        * <p>
        * For a user-defined function, this saves the given value as the function
        * return value.
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnNormal(String label, boolean val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, logical.of(val), ReturnType.NORMAL);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsume()
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, null, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsumeTopLevel()
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, null, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block, consuming any pending event processing. Sets
        * the <code>RETURN-VALUE</code> to the given value for internal/external
        * procedures and triggers. Should not be called for a user-defined
        * function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsume(character val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, val, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block, consuming any pending event processing. Sets
        * the <code>RETURN-VALUE</code> to the given value for internal/external
        * procedures and triggers. Should not be called for a user-defined
        * function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsumeTopLevel(character val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, val, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsume(String label)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, null, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block, consuming any pending event processing. Sets
        * the <code>RETURN-VALUE</code> to the given value for internal/external
        * procedures and triggers. Should not be called for a user-defined
        * function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsume(String label, character val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, val, ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block, consuming any pending event processing. Sets
        * the <code>RETURN-VALUE</code> to the given value for internal/external
        * procedures and triggers. Should not be called for a user-defined
        * function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsume(String label, String val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, new character(val), ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block, consuming any pending event processing. Sets
        * the <code>RETURN-VALUE</code> to the given value for internal/external
        * procedures and triggers. Should not be called for a user-defined
        * function.
        * <p>
        * If executed for a trigger, force the event which caused the trigger
        * execution to be consumed (no default processing of that event should
        * occur).
        *
        * @param    val
        *           The value to return or <code>null</code>.
        *
        * @throws   ReturnUnwindException
        */
       public static void undoReturnConsumeTopLevel(String val)
       throws ReturnUnwindException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, new character(val), ReturnType.CONSUME);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnError()
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, null, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnErrorTopLevel()
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, null, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. Sets the default <code>RETURN-VALUE</code>
        * to "" (empty string) for internal/external procedures and triggers.
        * Leaves <code>unknown value</code> as the default return from a
        * user-defined function.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnError(String label)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, null, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of the current block and then return from the nearest
        * enclosing top-level block. If the given value is <code>null</code>,
        * this sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. It leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.  If the value is not <code>null</code>, then that value (if
        * it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnError(character val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback();
          returnWorker(wa, val, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block. If the given value is <code>null</code>,
        * this sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. It leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.  If the value is not <code>null</code>, then that value (if
        * it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnErrorTopLevel(character val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, val, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. If the given value is <code>null</code>,
        * this sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. It leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.  If the value is not <code>null</code>, then that value (if
        * it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnError(String label, character val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, val, ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of the given block and then return from the nearest
        * enclosing top-level block. If the given value is <code>null</code>,
        * this sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. It leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.  If the value is not <code>null</code>, then that value (if
        * it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    label
        *           The name of the block that is the target of the undo
        *           operation.
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnError(String label, String val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollback(label);
          returnWorker(wa, new character(val), ReturnType.ERROR);
       }

       /**
        * Trigger a rollback of and then return from the nearest
        * enclosing top-level block. If the given value is <code>null</code>,
        * this sets the default <code>RETURN-VALUE</code> to "" (empty string)
        * for internal/external procedures and triggers. It leaves
        * <code>unknown value</code> as the default return from a user-defined
        * function.  If the value is not <code>null</code>, then that value (if
        * it is a <code>character</code> type) will be set as the
        * <code>RETURN-VALUE</code> for internal/external procedures and triggers.
        * If not <code>null</code>, the value will be returned as the function
        * return value for user-defined functions.
        * <p>
        * If silent error mode is not enabled in the caller, an <code>ERROR</code>
        * condition will be raised here and will unwind the stack (it will not
        * be processed, but will instead it will be rethrown) until it reaches
        * the caller's context at which time the error will be honored. If silent
        * error mode is enabled, the error data will be stored in the
        * <code>ERROR-STATUS</code> facility and a return will be executed to
        * return processing to the caller without raising the error condition
        * (without throwing an exception).
        *
        * @param    val
        *           The value to return.
        *
        * @throws   ReturnUnwindException
        * @throws   ErrorConditionException
        */
       public static void undoReturnErrorTopLevel(String val)
       throws ReturnUnwindException,
              ErrorConditionException
       {
          WorkArea wa = work.obtain();

          wa.tm.rollbackTopLevel();
          returnWorker(wa, new character(val), ReturnType.ERROR);
       }

       /**
        * Check if the top-level block is ROUTINE-LEVEL UNDO, THROW or the current program is
        * BLOCK-LEVEL UNDO, THROW.
        *
        * @return  see above.
        */
       static boolean mustManageLegacyError()
       {
          return mustManageLegacyError(work.obtain());
       }

       /**
        * Check if the top-level block is ROUTINE-LEVEL UNDO, THROW or the current program is
        * BLOCK-LEVEL UNDO, THROW.
        *
        * @param   wa
        *          The {@link WorkArea} instance.
        * @param   forceBlockLevelUndoThrow
        *          Flag indicating that, when nothing else matches, a BLOCK-LEVEL UNDO, THROW exists by default.
        *
        * @return  see above.
        */
       static boolean mustManageLegacyError(WorkArea wa, boolean forceBlockLevelUndoThrow)
       {
          return wa.pm._thisProcedure() != null &&
                (forceBlockLevelUndoThrow ||
                 (wa.tm.isRootNestingLevel() && AppServerManager.isRemote() && wa.pm.isRoutineLevelUndoThrow()) ||
                 (wa.tm.isTopLevelBlock() && wa.pm.isRoutineLevelUndoThrow())                                   ||
                 wa.pm.isBlockLevelUndoThrow());
       }
       /**
        * Check if the top-level block is ROUTINE-LEVEL UNDO, THROW or the current program is
        * BLOCK-LEVEL UNDO, THROW.
        *
        * @param   forceBlockLevelUndoThrow
        *          Flag indicating that, when nothing else matches, a BLOCK-LEVEL UNDO, THROW exists by default.
        *
        * @return  see above.
        */
       static boolean mustManageLegacyError(boolean forceBlockLevelUndoThrow)
       {
          return mustManageLegacyError(work.obtain(), forceBlockLevelUndoThrow);
       }

       /**
        * Check if the top-level block is ROUTINE-LEVEL UNDO, THROW or the current program is
        * BLOCK-LEVEL UNDO, THROW.
        *
        * @param   wa
        *          The {@link WorkArea} instance.
        *
        * @return  see above.
        */
       static boolean mustManageLegacyError(WorkArea wa)
       {
          return wa.pm._thisProcedure() != null &&
                ((wa.tm.isRootNestingLevel() && AppServerManager.isRemote() && wa.pm.isRoutineLevelUndoThrow()) ||
                 (wa.tm.isTopLevelBlock() && wa.pm.isRoutineLevelUndoThrow())                                   ||
                 wa.pm.isBlockLevelUndoThrow());
       }

       /**
        * Check whether the -catchStop startup parameter is set on 1.
        *
        * @param   wa
        *          The {@link WorkArea} instance.
        *
        * @return  see above.
        */
       static boolean mustManageLegacyStop(WorkArea wa)
       {
          return wa.catchStopParameter != 0;
       }

       /**
        * Check if we must throw a legacy compatible OO error.  This will happen if either
        * {@link #mustManageLegacyError()} or anywhere on the stack the specified error is handled
        * by a CATCH block.
        *
        * @param   errorClass
        *          The error class to be throw.
        *
        * @return  See above.
        */
       static boolean mustThrowLegacyError(Class<? extends LegacyError> errorClass)
       {
          return mustThrowLegacyError(work.obtain(), errorClass);
       }

       /**
        * Check if we must throw a legacy compatible OO error.  This will happen if either
        * {@link #mustManageLegacyError()} or anywhere on the stack the specified error is handled
        * by a CATCH block.
        *
        * @param   errorClass
        *          The error class to be throw.
        *
        * @return  See above.
        */
       static boolean mustThrowLegacyError(WorkArea wa, Class<? extends LegacyError> errorClass)
       {
          return mustManageLegacyError(wa) || hasLegacyError(wa, errorClass, 1);
       }

       /**
        * Check if any CATCH blocks defined at the specified enclosing block can manage this exception.
        * <p>
        * If none found, ignore this exception.  4GL doesn't seem to propagate the errors further than
        * then current block.
        *
        * @param    type
        *           The error type to process.
        * @param    levels
        *           Flag indicating which block to use (0 for current, 1 for parent, etc).  Use -1 to search the
        *           entire stack.
        *
        * @return   <code>true</code> if this exception can be processed by the current block.
        */
       static boolean hasLegacyError(Class<? extends LegacyError> type, int levels)
       {
          return hasLegacyError(work.obtain(), type, levels);
       }

       /**
        * Check if any CATCH blocks defined at the specified enclosing block can manage this stop exception.
        * <p>
        * If none found, ignore this exception.  4GL doesn't seem to propagate the errors further than
        * then current block.
        *
        * @param    type
        *           The error type to process.
        * @param    levels
        *           Flag indicating which block to use (0 for current, 1 for parent, etc).  Use -1 to search the
        *           entire stack.
        *
        * @return   <code>true</code> if this exception can be processed by the current block.
        */
       static boolean hasLegacyStop(Class<? extends Stop> type)
       {
          return hasLegacyStop(work.obtain(), type);
       }

       /**
        * Returns the type of return processing from the nearest top-level block.
        * The returned value is the value passed to {@link #returnWorker(WorkArea, Object, ReturnType)}.
        * <p>
        * The value is valid from the time the converted code implementing the top-level
        * block is exited until after {@link Scopeable#scopeFinished()} is called.
        *
        * @return   Type of return processing value or <code>null</code> if the nearest
        *           top-level code is not finished by execution of
        *           {@link #returnWorker(WorkArea, Object, ReturnType)}.
        */
       static ReturnType getReturnType()
       {
          return work.get().rtype;
       }

       /**
        * Get the function's return value.
        *
        * @return   The latest {@link WorkArea#funcRet} value.
        */
       static Object getFunctionReturn()
       {
          Object ret = work.get().funcRet.peek();
          return ret == null || ret == NULL ? null : ret;
       }

       /**
        * Check the {@link WorkArea#funcRet} stack for the supplied condition.
        *
        * @param    func
        *           The condition to check.
        *
        * @return   <code>true</code> if the condition applies to any of object in the return stack.
        */
       static boolean checkFunctionReturn(Function<Object, Boolean> func)
       {
          // only the top caller can have something to return 'in progress', everything else is still executing
          Object ret = work.get().funcRet.peek();
          if (ret == null)
          {
             return false;
          }

          if (ret.getClass().isArray())
          {
             int size = Array.getLength(ret);
             for (int j = 0; j < size; j++)
             {
                Object aret = Array.get(ret, j);
                if (func.apply(aret))
                {
                   return true;
                }
             }
          }
          else
          {
             return func.apply(ret);
          }

          return false;
       }

       /**
        * Get an instance of {@link ProcedureHelper}, which has the context-local instance saved,
        * so API access can be done without a context-local query.
        *
        * @return   See above.
        */
       static BlockManagerHelper getHelper()
       {
          return new BlockManagerHelper(work.get());
       }

       /**
        * Check if the <code>ErrorConditionException</code> was triggered in the caller and
        * throw a <code>LegacyErrorException</code>
        *
        * @param exc
        *        The RuntimeException to propagate
        */
       private static void checkLegacyError(RuntimeException exc)
       {
          if (exc instanceof ErrorConditionException && ((ErrorConditionException) exc).isTriggeredInCaller())
          {
             object<? extends SysError> legacyError = SysError.newInstance(
                     exc.getMessage(),
                     ((ErrorConditionException) exc).getProgressErrorCode());
             throw new LegacyErrorException(legacyError);
          }
          throw exc;
       }

       /**
        * Execute the given top-level block with the given transaction level.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  For external procedures, if this is non-null, then <code>block</code>
        *           can be an instance created using lambdas.  If <code>null</code>, then
        *           <code>block</code> MUST BE an anonymous inner class of the containing business
        *           logic instance so that instance can be calculated via reflection. For internal
        *           procedures and triggers, this is expected to be <code>null</code>.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    lvl
        *           The transaction level for the given block.
        * @param    btype
        *           The type of block represented by the given code.
        * @param    block
        *           The code to execute.
        */
       static void topLevelBlock(Class<?>        def,
                                 Object          referent,
                                 String          legacyName,
                                 TransactionType lvl,
                                 BlockType       btype,
                                 Block           block)
       {
          long start = 0;
          if (statsFile != null)
          {
             start = System.currentTimeMillis();
          }

          if (def == null && referent != null && referent.getClass() == Class.class)
          {
             def = (Class<?>) referent;
          }

          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();

          int     ttype = convertTransType(lvl, btype);
          boolean etype = (btype == BlockType.EXTERNAL_PROC);
          boolean ptype = (btype == BlockType.INTERNAL_PROC);

          WorkArea wa = work.obtain();

          // this checks if current block if current is either:
          // - session database trigger, so with trigger block type
          // - schema database trigger, so with external procedure block type
          //   and database trigger referent
          boolean databaseTrigger = (etype                       &&
                                     referent != null            &&
                                     referent instanceof com.goldencode.p2j.persist.trigger.DatabaseTrigger) ||
                                    btype == BlockType.DATABASETRIGGER;

          // external and internal procedures are allowed to be invoked outside of ControlFlowOps APIs
          // only from hand-written java code, but the conversion code emits only ControlFlowOps APIs
          // constructors are also invoked without ControlFlowOps APIs (emulated via internal proc).
          boolean javaCall = (etype || ptype);
          if (javaCall)
          {
              Boolean check = checkJavaCall(wa, def, referent, legacyName, block, false, etype, false);
              if (check == null)
              {
                 return;
              }
              javaCall = check;
          }

          OutputParameterAssigner opa = wa.tm.deregisterOutputParameterAssigner();
          String calleeName = ""; // opa will need this back when performing exit checks

          wa.tm.pushScope("methodScope",
                          ttype,
                          (PROP_ERROR | PROP_ENDKEY),
                          etype,
                          true,
                          false,
                          false,
                          databaseTrigger,
                          btype);

          // add a scope to our list of function return values and block types
          wa.topType.push(btype);

          try
          {
             methodScope:
             {
                // give the block a chance to initialize its state and don't
                // repeat that during retry
                block.init();

                wa.tm.blockSetup();

                do
                {
                   try
                   {
                      processBody(wa, block, null, null);
                   }

                   catch (LegacyErrorException lex)
                   {
                      processLegacyException(wa, lex);
                   }

                   catch (LegacyStopException lex)
                   {
                      processLegacyStopException(wa, lex);
                   }

                   catch (ErrorConditionException err)
                   {
                      wa.tm.notifyCondition(err);
                      wa.tm.honorError(err);
                      wa.tm.rollback("methodScope");
                      wa.tm.triggerRetry("methodScope");
                   }

                   catch (StopConditionException err)
                   {
                      wa.tm.notifyCondition(err);
                      wa.tm.rollback("methodScope");
                      throw err;
                   }

                   catch (InvalidParameterConditionException ipe)
                   {
                      wa.tm.notifyCondition(Condition.ERROR);
                      wa.tm.rollback("methodScope");
                      throw new ErrorConditionException(ipe.getCause());
                   }

                   catch (EndConditionException end)
                   {
                      wa.tm.notifyCondition(end);
                      wa.tm.rollback("methodScope");
                      break methodScope;
                   }

                   catch (RetryUnwindException rue)
                   {
                      wa.tm.honorRetry(rue);
                   }

                   catch (StackUnwindException sue)
                   {
                      // we have unwound to the exit point, break out (it doesn't
                      // matter whether we need to exit because of a LEAVE, NEXT
                      // or a RETURN, they all have the same result on a top-level
                      // block
                      break methodScope;
                   }

                   catch (Throwable thr)
                   {
                      wa.tm.abnormalEnd(thr);
                   }
                }
                while (wa.tm.needsRetry());
             }
          }
          catch (RuntimeException exc)
          {
             // cleaning up the OPA inside this catch only works because "normal"
             // control flow exceptions are caught and handled before they would
             // cross the top-level block boundary
             if (opa != null)
             {
                opa.abort();
             }
             checkLegacyError(exc);
          }
          finally
          {
             if (opa != null)
             {
                if (wa.rtype == BlockManager.ReturnType.ERROR)
                {
                   opa.abort();
                }
                else
                {
                   calleeName = wa.pm.getStackEntry(0);
                }
             }

             try
             {
                wa.tm.popScope();

             }
             catch (RuntimeException exc)
             {
                if (opa != null)
                {
                   opa.abort();
                }

                throw exc;
             }
             finally
             {
                // cleanup our top level block state
                exitTopLevel(wa);
                wa.rtype = null;

                if (javaCall && (etype || ptype))
                {
                   wa.pm.popCalleeInfo();
                }
             }

             if (statsFile != null)
             {
                recordExecutionStats(btype, block, start);
             }
          }

          // process assign-backs to database fields from output parameters, if any
          if (opa != null &&
              (btype == BlockType.EXTERNAL_PROC ||
               btype == BlockType.INTERNAL_PROC))
          {
             opa.processAssignments(calleeName, !(etype || ptype));
          }
       }

       /**
        * Register the abend code to be executed when the next top-level block needs to be invoked, as the
        * argument assignment failed.
        *
        * @param    abend
        *           The code to execute instead of the top-level block.
        */
       static void ignoreNextCall(Runnable abend)
       {
          WorkArea wa = work.get();
          if (wa.ignoreNextCall == null)
          {
             wa.ignoreNextCall = abend;
          }
       }

       /**
        * If the error referenced is an {@link AppError}, then also set the
        * {@link ControlFlowOps#setReturnValue RETURN-VALUE}.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    err
        *           The error being processed.
        *
        * @return   <code>true</code> if this is referencing an {@link AppError} instance.
        */
       private static boolean setReturnValue(WorkArea wa, LegacyError err)
       {
          boolean fromRetVal = false;
          if (err instanceof AppError)
          {
             character retVal = ((AppError) err).getReturnValue();
             fromRetVal = true;

             if (retVal != null && !retVal.isUnknown() && !retVal.toStringMessage().isEmpty())
             {
                wa.cfops.setReturnValue(retVal);
             }
          }

          return fromRetVal;
       }

       /**
        * Break out of the block associated with the given label.  This will
        * unwind the stack until the proper block has been reached.  At that
        * point the block will be left using the Java "break" statement.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    label
        *           The name of the block to be left.
        *
        * @throws   LeaveUnwindException
        */
       private static void leave(WorkArea wa, String label)
       throws LeaveUnwindException
       {
          if (label != null)
          {
             wa.deferredLeave = label;
          }

          throw wa.leaveExc;
       }

       /**
        * Continue (iterate) the block associated with the given label.  This will
        * unwind the stack until the proper block has been reached.  At that
        * point the block will be iterated using the Java "continue" statement.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    label
        *           The name of the block to be iterated.
        * @throws   NextUnwindException
        */
       private static void next(WorkArea wa, String label)
       throws NextUnwindException
       {
          if (label != null)
          {
             wa.deferredNext = label;
          }

          throw wa.nextExc;
       }

       /**
        * Check if we this call is a java-style call or is from {@link ControlFlowOps} APIs. If is
        * not from {@link ControlFlowOps}, then resolve {@link ProcedureManager.ProcedureHelper#pushCalleeInfo push
        * the callee info}.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    referent
        *           The instance of the containing business logic class from which this is being
        *           called.  For external procedures, if this is non-null, then <code>block</code>
        *           can be an instance created using lambdas.  If <code>null</code>, then
        *           <code>block</code> MUST BE an anonymous inner class of the containing business
        *           logic instance so that instance can be calculated via reflection. For internal
        *           procedures and functions, this is expected to be <code>null</code>.
        * @param    def
        *           The currently executing OE class or external program.
        * @param    legacyName
        *           The legacy name associated with the function/procedure being invoked via a
        *           java-style call.  If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    block
        *           The {@link Block} insance beeing executed.
        * @param    function
        *           Flag indicating if we are calling a function.
        * @param    externalProgram
        *           Flag indicating if we are calling an external program.
        * @param    persistentProc
        *           Flag indicating if the called external program is persistent.
        *
        * @return   {@code true} if we are in a java-style call, <code>null</code> if we need to abend.
        */
       private static Boolean checkJavaCall(WorkArea wa,
                                            Class<?> def,
                                            Object   referent,
                                            String   legacyName,
                                            Block    block,
                                            boolean  function,
                                            boolean  externalProgram,
                                            boolean  persistentProc)
       {
          if (referent != null && referent instanceof Class)
          {
             // there is at least a case where ObjectOps.load is emitted in the Block.init method,
             // and not in the Java method.  Anyway, we always emit the 'class referent', so we can
             // load it here
             wa.objHelper.load((Class) referent);
          }

          boolean javaCall = !wa.pendingDynCall;
          wa.pendingDynCall = false;

          if (wa.ignoreNextCall != null)
          {
             try
             {
                wa.ignoreNextCall.run();
             }
             finally
             {
                wa.ignoreNextCall = null;
             }

             return null;
          }

          if (javaCall)
          {
             String iename;
             String pname;

             Class<?> defref = def;

             if (externalProgram)
             {
                // OO method call has a non-null referent
                if (referent == null)
                {
                   referent = ProcedureManager.findRootEnclosingInstance(block);
                }
                else if (referent instanceof Class)
                {
                   defref = (Class<?>) referent;
                   referent = ObjectOps.getStaticInstance((Class<? extends _BaseObject_>) referent);
                }

                // safety first, this call won't work
                if (referent == null)
                {
                   ErrorManager.handleStopException("Invalid referent in external procedure call.");
                }

                iename = ProcedureManager.EXTERNAL_PROGRAM;
                pname = SourceNameMapper.convertJavaProgSafe(referent.getClass().getName());
             }
             else
             {
                // OO method call has a non-null referent
                if (referent == null)
                {
                   referent = wa.pm._thisProcedure();
                }
                else if (referent instanceof Class)
                {
                   defref = (Class<?>) referent;
                   referent = ObjectOps.getStaticInstance((Class<? extends _BaseObject_>) referent);
                }

                // we need to determine the legacy name of this call, so we can push it to the call
                // stack. fortunately, unlike the external program names, the internal entry names are
                // reported as they are defined, not called
                if (legacyName == null)
                {
                   iename = ProcedureManager.resolveClosestMethod(referent, function, externalProgram);
                }
                else
                {
                   iename = legacyName;
                }
                pname = null;
             }

             if (defref == null)
             {
                if (referent.getClass() == Class.class)
                {
                   defref = (Class<?>) referent;
                }
                else if (referent.getClass() == Object.class)
                {
                   defref = ObjectOps.getStaticClass(referent);
                }
                else
                {
                   defref = referent.getClass();
                }
             }
             wa.pm.pushCalleeInfo(defref, false, referent, referent, iename, pname, function, persistentProc);
             wa.pm.peekCalleeInfo().setLegacyName(iename);
          }

          return javaCall;
       }

       /**
        * Implements the body of all blocks or loops that are not related to the
        * <code>FOR</code> language statement. The main feature is to ensure that
        * any normal exit from the body will notify any <code>Commitable</code>
        * instances for validation purposes. A normal exit is a non-exception
        * return from {@link Block#body}, or certain exception cases related to
        * <code>LEAVE</code>, <code>NEXT</code>, <code>RETURN</code> or
        * <code>QUIT</code> when they are not associated with an <code>UNDO</code>.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    block
        *           The block to execute.
        * @param    on
        *           List of user-defined ON phrases.  May be {@code null}.
        * @param    defOn
        *           List of implicit ON phrases for this block.  May be {@code null}.
        */
       private static void processBody(WorkArea wa, Block block, OnPhrase[] on, OnPhrase[] defOn)
       throws Throwable
       {
          Throwable reason = null;

          try
          {
             // check the interrupted status and throw the stop condition if needed
             wa.tm.honorStopCondition();

             block.body();

             // check the interrupted status and throw the stop condition if needed
             wa.tm.honorStopCondition();
          }
          catch (DeferredLegacyErrorException dlex)
          {
             LegacyErrorException lex = ErrorManager.getDeferredLegacyError();
             processLegacyError(wa, lex, on, defOn);
          }
          catch (LegacyErrorException lex)
          {
             processLegacyError(wa, lex, on, defOn);
          }
          catch (DeferredLegacyStopException dlex)
          {
             LegacyStopException lex = ErrorManager.getDeferredLegacyStop();
             processLegacyStop(wa, lex);
          }
          catch (LegacyStopException lex)
          {
             processLegacyStop(wa, lex);
          }
          catch (ConditionException e)
          {
             wa.tm.errHlp.addNumbersToConditionException(e);
             reason = e;
          }
          catch (Throwable thr)
          {
             reason = thr;
          }
          finally
          {
             if (wa.tm.isTransaction() && (reason == null || isNormal(wa, reason, on)))
             {
                executeStateManaged(wa, wa.tm::processValidate);
             }

             // the body executed at least once, so the fini() method must be called too
             if (block.hasFini())
             {
                // we cannot execute the FINALLY block here; it must be deferred to the end of iterate,
                // retry or block exit

                TransactionType lvl = block.finiMethod.getTransactionType();
                Block finiAsBlock = new Block((Body) block::fini);
                wa.tm.setupFinallyBlock(() -> doTerminationBlockWorker(wa,
                                                                       lvl,
                                                                       FINALLY_BLOCK_LABEL,
                                                                       true,
                                                                       finiAsBlock));
             }

             if (reason != null)
             {
                throw reason;
             }
          }
       }

       /**
        * Implements the body of all <code>FOR</code> language statement blocks or
        * loops. The main feature is to ensure that any normal exit from the body
        * will notify any <code>Commitable</code> instances for validation
        * purposes. A normal exit is a non-exception return from {@link Block#body},
        * or certain exception cases related to <code>LEAVE</code>,
        * <code>NEXT</code>, <code>RETURN</code> or <code>QUIT</code> when they are
        * not associated with an <code>UNDO</code>.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    block
        *           The block to execute.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined ON phrases.  May be {@code null}.
        * @param    defOn
        *           List of implicit ON phrases for this block.  May be {@code null}.
        *
        * @return   <code>true</code> if the code should break out of the block
        *           on return (because the loop/block control expressions or
        *           incrementer forced an exit).
        */
       private static boolean processForBody(WorkArea   wa,
                                             Block      block,
                                             ToClause   to,
                                             LogicalOp  expr,
                                             OnPhrase[] on,
                                             OnPhrase[] defOn)
       throws Throwable
       {
          Throwable reason     = null;
          boolean   needsBreak = false;
          boolean   bodyRan    = false;

          try
          {
             wa.tm.honorStopCondition();
             // retrieve the record (only used in cases where there is a TO and/or WHILE)
             if (to != null || expr != null)
             {
                block.enter();
             }

             // evaluate any TO or WHILE condition and execute the block
             // body if both are null or when all non-null expressions
             // evaluate true; otherwise never execute the block body
             if (needsIterate(to, expr))
             {
                bodyRan = true;
                block.body();

                wa.tm.honorStopCondition();
             }
             else
             {
                needsBreak = true;
             }
          }
          catch (DeferredLegacyErrorException dlex)
          {
             LegacyErrorException lex = ErrorManager.getDeferredLegacyError();
             processLegacyError(wa, lex, on, defOn);
          }
          catch (LegacyErrorException lex)
          {
             processLegacyError(wa, lex, on, defOn);
          }
          catch (DeferredLegacyStopException dlex)
          {
             LegacyStopException lex = ErrorManager.getDeferredLegacyStop();
             processLegacyStop(wa, lex);
          }
          catch (LegacyStopException lex)
          {
             processLegacyStop(wa, lex);
          }

          catch (Throwable thr)
          {
             // for now, we are still processing the query as the first statement in the body
             // but this is known to cause some deviations in transaction state; one of the
             // problems that we fixup here is that the body doesn't really execute in this
             // case but without this code we would think that it had executed
             if (thr instanceof QueryOffEndException)
             {
                bodyRan = false;
             }

             reason = thr;
          }
          finally
          {
             if (reason == null || isNormal(wa, reason, on))
             {
                executeStateManaged(wa, wa.tm::processValidate);
             }

             // if the body executed then the fini() method must be called too
             if (bodyRan && block.hasFini())
             {
                // we cannot execute the FINALLY block here; it must be deferred to the end of iterate,
                // retry or block exit

                TransactionType lvl = block.finiMethod.getTransactionType();
                Block finiAsBlock = new Block((Body) block::fini);
                wa.tm.setupFinallyBlock(() -> doTerminationBlockWorker(wa,
                                                                       lvl,
                                                                       FINALLY_BLOCK_LABEL,
                                                                       true,
                                                                       finiAsBlock));
             }

             if (reason != null)
             {
                throw reason;
             }
          }

          return needsBreak;
       }

       /**
        * Detect if an exception represents a normal or abnormal condition.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    thr
        *           The exception to analyze.
        * @param    on
        *           List of user-defined on phrases.
        *
        * @return   <code>true</code> if the exception is a normal control-flow
        *           condition.
        */
       private static boolean isNormal(WorkArea wa, Throwable thr, OnPhrase[] on)
       {
          // no exception means normal
          if (thr == null)
          {
             return true;
          }

          // LEAVE, NEXT and RETURN
          if (thr instanceof StackUnwindException)
          {
             // check if an UNDO is NOT in effect
             if (!wa.tm.hadRollback())
             {
                return true;
             }
          }

          // QUIT
          if (thr instanceof QuitConditionException)
          {
             // if there are no user-defined ON phrases, then a QUIT is always
             // a commit instead of a rollback
             if (on == null)
             {
                return true;
             }

             // look for a user-defined ON QUIT phrase
             OnPhrase imple = matchCondition(on, null, Condition.QUIT);

             // if none, then QUIT will be a commit not a rollback
             if (imple == null)
             {
                return true;
             }
          }

          return false;
       }

       /**
        * Detect if there is a pending leave for the block named by the given
        * label. If so, this deferred leave flag will be cleared and
        * <code>true</code> will be returned.  The caller is responsible for
        * ensuring that the leave request is fully granted as no further state
        * will be available for subsequent processing.
        *
        * @param    wa
        *           Local context.
        * @param    label
        *           The name of the block to be checked against the deferred
        *           leave block name.
        *
        * @return   <code>true</code> if there is a pending deferred leave and
        *           the name of the block to be left is the same as the given
        *           label. If the pending deferred block name is the "" (empty
        *           string), that is the equivalent of matching "any block" and
        *           so the first call to this method after that is set will cause
        *           a <code>true</code> to be returned.
        */
       private static boolean deferredLeaveWorker(WorkArea wa, String label)
       {
          if (wa == null)
             wa = work.obtain();

          if (wa.deferredLeave != null && label != null)
          {
             if (label.equals(wa.deferredLeave) || wa.deferredLeave.length() == 0)
             {
                // clear state
                wa.deferredLeave = null;

                return true;
             }
          }

          return false;
       }

       /**
        * Detect if there is a pending next for the block named by the given
        * label. If so, this deferred next flag will be cleared and
        * <code>true</code> will be returned.  The caller is responsible for
        * ensuring that the next request is fully granted as no further state
        * will be available for subsequent processing.
        *
        * @param    wa
        *           Local context.
        * @param    label
        *           The name of the block to be checked against the deferred
        *           next block name.
        *
        * @return   <code>true</code> if there is a pending deferred next and
        *           the name of the block to be iterated is the same as the given
        *           label. If the pending deferred block name is the "" (empty
        *           string), that is the equivalent of matching "any block" and
        *           so the first call to this method after that is set will cause
        *           a <code>true</code> to be returned.
        */
       private static boolean deferredNextWorker(WorkArea wa, String label)
       {
          if (wa == null)
             wa = work.obtain();

          if (wa.deferredNext != null && label != null)
          {
             if (label.equals(wa.deferredNext) || wa.deferredNext.length() == 0)
             {
                // clear state
                wa.deferredNext = null;

                return true;
             }
          }

          return false;
       }

       /**
        * Return from the nearest enclosing top-level block. This will process
        * differently based on the type of the top-level block (internal/external
        * procedures, triggers or user-defined functions), the type of return
        * processing that is requested (see {@link ReturnType}) and the presence
        * or absence of a value to return.
        * <p>
        * The following behavior is provided:
        * <p>
        * <pre>
        * Codes   Meaning
        * ------  -----------------------------------------------------
        * C       Invoke LogicalTerminal.consume()
        * E       Invoke TransactionManager.triggerErrorInCaller()
        * V       Invoke ControlFlowOps.setReturnValue(val)
        * N       Invoke ControlFlowOps.setReturnValue("")
        * F       Invoke setFuncReturn(val)
        * U       Invoke setFuncReturn(null) (set return value as unknown)
        * I       Invalid (compile error in Progress)
        *
        *  Return    Return    Internal  External  Trigger  Function
        *  Value      Type       Proc      Proc
        * --------  ---------  --------  --------  -------  --------
        * null      NORMAL     N         N         N        U
        * non-null  NORMAL     V         V         V        F
        * null      CONSUME    N         N         NC       U
        * non-null  CONSUME    V         V         VC       F
        * null      ERROR      NE        NE        I        U
        * non-null  ERROR      VE        VE        I        U
        * </pre>
        * <p>
        * In all cases, a {@link ReturnUnwindException} will be thrown and this
        * will cause the stack to unwind to the nearest enclosing top-level
        * block. That block will then handle the return in a block specific
        * manner.  For example, in a user-defined function, the given value or
        * by default the <code>unknown value</code> will be returned to the
        * caller. Procedures and triggers have void return values.
        *
        * @param    val
        *           The value to return.
        * @param    rtype
        *           The type of return processing.
        */
       private static void returnWorker(BaseDataType val, ReturnType rtype)
       throws ReturnUnwindException
       {
          returnWorker(null, val, rtype);
       }

       /**
        * Return from the nearest enclosing top-level block. This will process
        * differently based on the type of the top-level block (internal/external
        * procedures, triggers or user-defined functions), the type of return
        * processing that is requested (see {@link ReturnType}) and the presence
        * or absence of a value to return.
        * <p>
        * The following behavior is provided:
        * <p>
        * <pre>
        * Codes   Meaning
        * ------  -----------------------------------------------------
        * C       Invoke LogicalTerminal.consume()
        * E       Invoke TransactionManager.triggerErrorInCaller()
        * V       Invoke ControlFlowOps.setReturnValue(val)
        * N       Invoke ControlFlowOps.setReturnValue("")
        * F       Invoke setFuncReturn(val)
        * U       Invoke setFuncReturn(null) (set return value as unknown)
        * I       Invalid (compile error in Progress)
        *
        *  Return    Return    Internal  External  Trigger  Function
        *  Value      Type       Proc      Proc
        * --------  ---------  --------  --------  -------  --------
        * null      NORMAL     N         N         N        U
        * non-null  NORMAL     V         V         V        F
        * null      CONSUME    N         N         NC       U
        * non-null  CONSUME    V         V         VC       F
        * null      ERROR      NE        NE        I        U
        * non-null  ERROR      VE        VE        I        U
        * </pre>
        * <p>
        * In all cases, a {@link ReturnUnwindException} will be thrown and this
        * will cause the stack to unwind to the nearest enclosing top-level
        * block. That block will then handle the return in a block specific
        * manner.  For example, in a user-defined function, the given value or
        * by default the <code>unknown value</code> will be returned to the
        * caller. Procedures and triggers have void return values.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in caller.
        * @param    val
        *           The value to return. If the function doesn't return an extent value, the element
        *           zero will be returned.
        * @param    rtype
        *           The type of return processing.
        */
       private static void returnWorker(WorkArea wa, Object val, ReturnType rtype)
       throws ReturnUnwindException
       {
          if (wa == null)
             wa = work.obtain();

          BlockType nearest = topLevelType(wa);
          boolean   skipThrowLegacyError = false;

          // save the return processing type
          boolean store = (rtype == ReturnType.STORE);
          boolean retError = (rtype == ReturnType.ERROR);
          if (retError)
          {
             markReturnError(wa);
          }

          if (store)
          {
             rtype = ReturnType.NORMAL;
          }
          wa.rtype = rtype;

          if (nearest != null)
          {
             switch (nearest)
             {
                case DATABASETRIGGER:
                case TRIGGER:
                   if (rtype == ReturnType.CONSUME)
                   {
                      LogicalTerminal.consumeEvent();
                   }
                   else if (retError)
                   {
                      String err = "RETURN ERROR is not allowed in a TRIGGER";
                      throw new IllegalArgumentException(err);
                   }
                   // fall through so that return-value is also set
                case INTERNAL_PROC:
                case EXTERNAL_PROC:
                   if (rtype == ReturnType.CONSUME && isPersistentTriggerTopLevel(wa))
                   {
                      LogicalTerminal.consumeEvent();
                   }

                   if (val == null)
                   {
                      wa.cfops.setReturnValue("");
                   }
                   else
                   {
                      // the return value should always be of type character
                      // but this code just makes it safer
                      if (val instanceof unknown)
                      {
                         wa.cfops.setReturnValue(new character());
                      }
                      else if (val instanceof character)
                      {
                         character retVal = (character) val;
                         wa.cfops.setReturnValue(retVal);
                      }
                   }
                   break;
                case FUNCTION:
                   // In the error case, even if a value is passed, it will be
                   // forced to null; in the non-error cases if the value is null
                   // then the result will be setting the return to unknown value
                   // and if the value is not null, then that value will be set as
                   // the return value.
                   setFuncReturn(retError ? null : val, wa, nearest);
                   // Quirk: 'return error' in ABL method *does* set error-status:error
                   //        to true, while an ABL function leaves error-status as is.
                   // Proof: xfer testcases rev 1274.
                   CalleeInfo calinfo = (retError ? wa.pm.peekCalleeInfo() : null);
                   // To avoid unnecessary peek calls, we only call isMethod() if needed further on.
                   if (calinfo == null || !calinfo.isMethod())
                   {
                      skipThrowLegacyError = true;
                   }
                   break;
                default:
                   break;
             }
          }

          // functions don't raise error in the calling scope, methods do.
          if (retError && !skipThrowLegacyError)
          {
             if (mustThrowLegacyError(wa, AppError.class))
             {
                try
                {
                   // reset before the 'newInstance' call
                   wa.rtype = null;

                   object<? extends AppError> err = AppError.newInstance(ControlFlowOps.getReturnValue());
                   err.ref.setFromReturn(true);
                   LegacyErrorException lex = new LegacyErrorException(err, true);
                   lex.setExplicit(true);
                   wa.tm.triggerErrorInCaller(lex);
                   throw lex;
                }
                finally
                {
                   // set this again, as it gets changed by 'AppError.newInstance'
                   wa.rtype = rtype;
                }
             }
             wa.tm.triggerErrorInCaller();
          }

          if (store)
          {
             // if 'storeReturnValue' is being called, then this is either the last RETURN in the block or is
             // always followed by a Java 'return'.
             return;
          }
          else if (rtype == ReturnType.NORMAL && wa.tm.getBlockType() == BlockType.FUNCTION)
          {
             // otherwise, check if this return can skip the exception throw

             Object thisProc = wa.pm._thisProcedure();
             String clsName = null;
             if (thisProc instanceof _BaseObject_)
             {
                clsName = thisProc.getClass().getName();
             }
             else if (thisProc.getClass() == Object.class)
             {
                // this case handles static OO method calls - for this, FWD uses a surrogate java.lang.Object
                // instance to be used as THIS-PROCEDURE; THIS-PROCEDURE is how FWD internally identifies the
                // context of the current call (and for static calls there is no 'instance', thus the
                // java.lang.Object surrogate).
                Class<? extends _BaseObject_> cls = ObjectOps.getStaticClass(thisProc);
                clsName = cls.getName();
             }

             // TODO: replace this test with cls.isAnnotation(LegacyResource.class) ?
             if (clsName != null && clsName.startsWith("com.goldencode.p2j.oo"))
             {
                // WARNING: the p2o.oo code is not refactored to use 'storeReturnValue' or Java return statements
                // instead, this code uses and expects for the returnNormal call to exit the block.
             }
             else
             {
                return;
             }
          }

          throw wa.retExc;
       }

       /**
        * Mark all blocks on the stack enclosed in this this top-level block (including it), as
        * {@link BlockDefinition#wasReturnError}.
        * <p>
        * This is called only when a RETURN ERORR (from within a top-level block) is being called, and is meant to
        * mark all blocks on the stack, up to the nearest top-level block, that the exist is being done via a
        * RETURN ERROR.
        * <p>
        * Do not call this method from other code.
        *
        * @param    wa
        *           The context-local instance.
        */
       private static void markReturnError(WorkArea wa)
       {
          int i = 0;
          BlockDefinition blk = wa.tm.getBlock(i);
          while (blk != null && !blk.topLevel)
          {
             blk.wasReturnError = true;
             i = i + 1;
             blk = wa.tm.getBlock(i);
          }
          if (blk != null)
          {
             // this is the nearest top-level block
             blk.wasReturnError = true;
          }
       }

       /**
        * Execute the given function block with the given transaction level.
        *
        * @param    def
        *           The Java class associated with a legacy OE class, if this code is part of a legacy
        *           OE class; otherwise, <code>null</code>.
        * @param    referent
        *           The referent to which this method belongs.
        * @param    legacyName
        *           The legacy name associated with the function being invoked via a java-style call.
        *           If is <code>null</code>, it will be resolved by
        *           {@link ProcedureManager#resolveClosestMethod}.
        * @param    level
        *           The transaction level for the given block.
        * @param    block
        *           The code to execute.
        * @param    retType
        *           The type of the return value which is used in the case the
        *           <code>unknown value</code> must be returned.
        * @param    extent
        *           For functions not returning an extent value, this is -1. Else, this extent size,
        *           which is 0 for dynamic-extent and &gt;0 for fixed extent.
        *
        * @return   The return value from the block (or its nested blocks) which
        *           is the <code>unknown value</code> by default or on error.
        */
       @SuppressWarnings("unchecked")
       private static <T extends BaseDataType> Object functionBlock(Class<?>        def,
                                                                    Object          referent,
                                                                    String          legacyName,
                                                                    TransactionType level,
                                                                    Block           block,
                                                                    Class<T>        retType,
                                                                    int             extent)
       {
          WorkArea wa = work.obtain();
          Boolean javaCall = checkJavaCall(wa, def, referent, legacyName, block, true, false, false);
          if (javaCall == null)
          {
             // terminate the call
             return BaseDataType.generateUnknown(retType);
          }

          if (object.class == retType || (retType.isArray() && object.class == retType.getComponentType()))
          {
             wa.objHelper.registerPendingScopeable();
          }

          long start = 0;

          if (statsFile != null)
          {
             start = System.currentTimeMillis();
          }

          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();

          OutputParameterAssigner opa = wa.tm.deregisterOutputParameterAssigner();
          String calleeName = ""; // opa will need this back when performing exit checks
          boolean wasDynamicCall = false;

          Object retVal = null;

          int ttype = convertTransType(level, BlockType.FUNCTION);
          wa.tm.pushScope("methodScope",
                          ttype,
                          (PROP_ERROR | PROP_ENDKEY),
                          false,
                          true,
                          false,
                          false,
                          BlockType.FUNCTION);

          // add a scope to our list of function return values and block types
          wa.funcRet.push(NULL);
          wa.topType.push(BlockType.FUNCTION);

          try
          {
             methodScope:
             {
                // give the block a chance to initialize its state and don't repeat that during retry
                block.init();

                wa.tm.blockSetup();

                do
                {
                   try
                   {
                      processBody(wa, block, null, null);
                   }

                   catch (LegacyErrorException lex)
                   {
                      processLegacyException(wa, lex);
                   }

                   catch (LegacyStopException lex)
                   {
                      processLegacyStopException(wa, lex);
                   }

                   catch (ErrorConditionException err)
                   {
                      // we deliberately do not test honorError() here since
                      // functions in Progress do not implement the "trigger
                      // error in caller" behavior on a return error
                      wa.tm.notifyCondition(err);
                      wa.tm.rollback("methodScope", err);
                      wa.tm.triggerRetry("methodScope");
                   }

                   catch (StopConditionException err)
                   {
                      wa.tm.notifyCondition(err);
                      wa.tm.rollback("methodScope", err);
                      throw err;
                   }

                   catch (EndConditionException end)
                   {
                      wa.tm.notifyCondition(end);
                      wa.tm.rollback("methodScope", end);
                      break methodScope;
                   }

                   catch (RetryUnwindException rue)
                   {
                      wa.tm.honorRetry(rue);
                   }

                   catch (StackUnwindException sue)
                   {
                      // we have unwound to the exit point, break out (it doesn't
                      // matter whether we need to exit because of a LEAVE, NEXT or
                      // a RETURN, they all have the same result on a function block
                      break methodScope;
                   }

                   catch (Throwable thr)
                   {
                      wa.tm.abnormalEnd(thr);
                   }
                }
                while (wa.tm.needsRetry());
             }
          }
          catch (RuntimeException exc)
          {
             // cleaning up the OPA inside this catch only works because "normal"
             // control flow exceptions are caught and handled before they would
             // cross the top-level block boundary
             if (opa != null)
             {
                opa.abort();
             }
             checkLegacyError(exc);
          }
          finally
          {
             if (opa != null)
             {
                if (wa.rtype == BlockManager.ReturnType.ERROR)
                {
                   opa.abort();
                }
                else
                {
                   calleeName = wa.pm.getStackEntry(0);
                }
             }

             try
             {
                wa.tm.popScope();
             }
             catch (RuntimeException exc)
             {
                if (opa != null)
                {
                   opa.abort();
                }

                throw exc;
             }
             finally
             {
                // cleanup return value stack and obtain the current value
                retVal = wa.funcRet.pop();
                if (retVal == NULL)
                {
                   retVal = null;
                }

                // cleanup our top level block state
                exitTopLevel(wa);

                wa.rtype = null;

                if (javaCall)
                {
                   wasDynamicCall = wa.pm.peekCalleeInfo().isDynamicCall();
                   wa.pm.popCalleeInfo();
                }
             }

             if (statsFile != null)
             {
                recordExecutionStats(BlockType.FUNCTION, block, start);
             }
          }

          // process assign-backs to database fields from output parameters, if any
          if (opa != null)
          {
             opa.processAssignments(calleeName, true);
          }

          // assume no-extent
          int size = 1;
          if (extent >= 0)
          {
             int retValLength = retVal == null
                                  ? extent
                                  : retVal.getClass().isArray() ? Array.getLength(retVal) : 1;
             if (extent > 0 && retVal != null && retValLength != extent)
             {
                // TODO: if fixed extent, it must be of the same size
             }

             size = retVal == null ? extent : retValLength;

             T[] ret = (T[]) Array.newInstance(retType, size);
             for (int i = 0; i < size; i++)
             {
                if (retVal == null)
                {
                   ret[i] = (T) BaseDataType.generateUnknown(retType);
                }
                else
                {
                   try
                   {
                      // In order to return the expected type, look for the "conversion" constructor
                      // of the type expected to return having as argument an object of the type
                      // we received in return statement. Then use it to create a new instance.
                      T t = null;
                      BaseDataType val = (BaseDataType) Array.get(retVal, i);

                      if (retType == memptr.class && val instanceof memptr)
                      {
                         t = (T) val;
                      }
                      else
                      {
                         t = (T) BaseDataTypeFactory.instantiate(retType);
                         t.assign((BaseDataType) val);
                      }
                      ret[i] = t;
                   }
                   catch (ConditionException ce)
                   {
                      // some 4GL validation/conversion error occurred
                      // propagate, will be handled elsewhere
                      throw ce;
                   }
                   catch (Exception ex)
                   {
                      Throwable ex2 = ex;
                      while (ex2 != null && !(ex2 instanceof ConditionException))
                      {
                         ex2 = ex2.getCause();
                      }

                      if (ex2 == null)
                      {
                         // wrap in a RunnableException and rethrow
                         throw new RuntimeException(ex);
                      }
                      else
                      {
                         // ex2 is instance of ConditionException because of a 4GL validation/conversion
                         // error has occurred: propagate, will be handled elsewhere
                         throw (ConditionException) ex2;
                      }
                   }
                }
             }

             return ret;
          }
          else
          {
             if (retVal == null)
             {
                return BaseDataType.generateUnknown(retType);
             }
             else
             {
                try
                {
                   BaseDataType ret;

                   if (memptr.class == retType && retVal instanceof memptr)
                   {
                      ret = (memptr) retVal;
                   }
                   else if ((retType == BaseDataType.class ||
                            BaseDataType.isProxy((BaseDataType) retVal) ||
                            ((javaCall && wasDynamicCall) ||
                             (!javaCall && wa.pm.peekCalleeInfo().isDynamicCall()))) &&
                            ((BaseDataType) retVal).val().getType().getCls() != retType)
                   {
                      // any dynamic function should provide a proxy for the return value instead:
                      // - in 4GL, returning a value which comes from a dynamic-function invocation
                      // can bypass the return data type
                      // - in Java, we should ensure that the returned value ALWAYS matches the defined return
                      // data type; that is why we encapsulate this value using a proxy
                      ret = BaseDataType.createProxy(((BaseDataType) retVal).val(),
                            (Class<? extends BaseDataType>) retType);
                   }
                   else
                   {
                      retVal = ((BaseDataType) retVal).val();
                      if (integer.class == retType && retVal instanceof int64)
                      {
                         ret = new integer()
                         {
                            @Override
                            boolean isAssignDirect()
                            {
                               return true;
                            }
                         };
                      }
                      else if (retType == object.class && ((object) retVal)._isValid())
                      {
                         // create a ObjectVar and register it with the current block - the return reference can
                         // end up only 'on the stack' as a return value, if the reference will never be assigned;
                         // more, ObjectOps.instanceReturned will prohibit the reference to be deleted (as it
                         // waits to 'maybe be assigned to something').

                         wa.objHelper.registerScopeable();

                         ret = new ObjectVar<>(((object) retVal).type());
                         wa.objHelper.registerObject((ObjectVar) ret);
                      }
                      else
                      {
                         ret = BaseDataTypeFactory.instantiate(retType);
                      }

                      ret.assign((BaseDataType) retVal);

                      // preserve case sensitivity of the returned value
                      if (retVal instanceof Text)
                      {
                         ((Text) ret).setCaseSensitive(((Text) retVal).isCaseSensitive());
                      }
                   }

                   return ret;
                }
                catch (ConditionException ce)
                {
                   // some 4GL validation/conversion error occurred
                   // propagate, will be handled elsewhere
                   throw ce;
                }
                catch (Exception ex)
                {
                   Throwable ex2 = ex;
                   while (ex2 != null && !(ex2 instanceof ConditionException))
                   {
                      ex2 = ex2.getCause();
                   }

                   if (ex2 == null)
                   {
                      // wrap in a RunnableException and rethrow
                      throw new RuntimeException(ex);
                   }
                   else
                   {
                      // ex2 is instance of ConditionException because of a 4GL validation/conversion
                      // error has occurred: propagate, will be handled elsewhere
                      throw (ConditionException) ex2;
                   }
                }
             }
          }
       }

       /**
        * Execute the given editing block for the given frame and widget list
        * with <code>UPDATE</code> semanics. All looping, sub-transaction
        * properties and block properties will be honored.  The exit from the
        * editing block will be based on the given <code>GO-ON</code> event list.
        *
        * @param    frame
        *           The frame for which the editing block is associated.
        * @param    widgets
        *           The widgets in the given frame that are to be enabled for
        *           editing.
        * @param    goOn
        *           The exit conditions for this loop or <code>null</code> if
        *           there are no explicit exit conditions.
        * @param    enclosing
        *           The list of enclosing blocks of which this class is unaware.
        *           Any LEAVE or NEXT that references one of those enclosing
        *           blocks must not unwind the stack further using an exception,
        *           but rather it must return and let the caller check to see if
        *           a deferred LEAVE or NEXT must be honored.
        * @param    label
        *           The label of the block for use in control flow statements
        *           such as <code>LEAVE</code> or <code>NEXT</code>.
        * @param    block
        *           The code for the editing block body.
        * @param    etype
        *           Editing block semantics (<code>CommonFrame.PROMPT-FOR</code>,
        *           <code>CommonFrame.SET</code> or
        *           <code>CommonFrame.UPDATE</code>).
        */
       private static void editingBlock(CommonFrame    frame,
                                        FrameElement[] widgets,
                                        EventList      goOn,
                                        String[]       enclosing,
                                        String         label,
                                        Block          block,
                                        int            etype)
       {
          boolean noWidgets = true;
          for (FrameElement el : widgets)
          {
             if (el != null)
             {
                noWidgets = false;
                break;
             }
          }

          if (noWidgets)
          {
             // the editing loop is a no-op if no widget was specified (as i.e. all WHEN clauses were
             // false)
             return;
          }

          if (UnnamedStreams.input() != null)
          {
             switch (etype)
             {
                case CommonFrame.PROMPT_FOR:
                {
                   frame.promptFor(widgets, goOn);
                   break;
                }
                case CommonFrame.SET:
                {
                   frame.set(widgets, goOn);
                   break;
                }
                case CommonFrame.UPDATE:
                {
                   frame.update(widgets, goOn);
                   break;
                }
             }

             return;
          }

          BufferManager.registerPendingScopeable(null);
          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();

          WorkArea wa = work.obtain();

          wa.tm.pushScope(label,
                          convertTransType(TransactionType.SUB, BlockType.EDITING),
                          PROP_ERROR,
                          false,
                          false,
                          true,
                          true,
                          BlockType.EDITING);

          try
          {
             // give the block a chance to initialize its state and don't
             // repeat that during retry
             block.init();

             // prepare the frame and the client for the editing block, this
             // must only occur once (outside of the loop body and not being
             // re-executed on retry)
             if (goOn == null)
             {
                frame.startEditingMode(widgets, etype);
             }
             else
             {
                frame.startEditingMode(widgets, etype, goOn);
             }

             boolean hadNext = false;

             editing:
             do
             {
                wa.tm.blockSetup();

                do
                {
                   // reset at the beginning of each iteration
                   hadNext = false;

                   try
                   {
                      processBody(wa, block, null, null);
                   }

                   catch (ErrorConditionException err)
                   {
                      wa.tm.notifyCondition(err);

                      // EDITING blocks propagate ERROR conditions to the
                      // containing block, in 2 cases:
                      // 1. PROMPT-FOR or SET semantics
                      // 2. No matter the type of editing block (even if it is
                      //    an UPDATE), if the condition was raised as a result
                      //    of the END-ERROR key AND the editing block's "local"
                      //    interaction number < 2
                      if (etype != CommonFrame.UPDATE ||
                          (err.isEndError() && (wa.tm.getInteractions() < 2)))
                      {
                         throw err;
                      }

                      // If the EDITING semantic is for an UPDATE type block AND
                      // the ERROR condition was NOT raised as a result of an
                      // END-ERROR key press if "local" interaction number < 2,
                      // then AND ONLY THEN we will act as if there was an UNDO,
                      // RETRY of the EDITING block.
                      wa.tm.honorError(err);
                      wa.tm.rollback(label, err);
                      wa.tm.triggerRetry(null);
                   }

                   catch (RetryUnwindException rue)
                   {
                      wa.tm.honorRetry(rue);
                   }

                   catch (LeaveUnwindException lue)
                   {
                      if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                      {
                         boolean res = LogicalTerminal.getClient().validateDisplayValue();
                         if (!res)
                         {
                            continue editing;
                         }

                         // the LEAVE targeted this block or an enclosing non-managed block
                         break editing;
                      }

                      // the LEAVE must be referencing an enclosing block which IS
                      // known to the block manager OR to one of the other
                      // enclosing managed blocks, so keep unwinding the stack
                      throw lue;
                   }

                   catch (NextUnwindException nue)
                   {
                      switch (testNext(wa, enclosing, label))
                      {
                         case BREAK:
                            // a NEXT targeted at a directly enclosing block that is not managed
                            break editing;

                         case CONTINUE:
                            // a NEXT targeted at this block
                            hadNext = true;
                            continue editing;

                         default:
                            // the NEXT must be referencing an enclosing block
                            // which IS known to the block manager OR to one of
                            // the other enclosing managed blocks, so keep
                            // unwinding the stack
                            throw nue;
                      }
                   }

                   catch (ReturnUnwindException ret)
                   {
                      // this isn't a top level block, keep unwinding without
                      // treating this as an abend
                      throw ret;
                   }

                   catch (Throwable thr)
                   {
                      wa.tm.abnormalEnd(thr);
                   }
                }
                while (wa.tm.needsRetry());

                if (wa.tm.isBreakPending())
                {
                   break editing;
                }
             }
             while (frame.continueEditing(widgets, hadNext));
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Execute a simple DO block (not a loop) with the given configuration and no default properties.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current block.
        * @param    label
        *           The block name of the current block.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       private static void doBlockWorker(TransactionType lvl,
                                         String[]        enclosing,
                                         String          label,
                                         OnPhrase[]      on,
                                         Block           block)
       {
          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();

          BlockType blockType = BlockType.DO;

          int ttype = convertTransType(lvl, blockType);

          OnPhrase[] defOn = null;

          if (lvl == TransactionType.FULL)
          {
             defOn = new OnPhrase[1];
             defOn[0] = new OnPhrase(Condition.ERROR, Action.RETRY, label);
          }

          int props = decodeConditions(defOn, on);

          WorkArea wa = work.obtain();

          wa.tm.pushScope(label, ttype, props, false, false, false, false, blockType);

          try
          {
             try
             {
                // each constructed query during block initialization will be
                // collected
                wa.tm.startOffEndRegistration();

                // give the block a chance to initialize its state and don't
                // repeat that during retry
                block.init();
             }
             finally
             {
                wa.tm.stopOffEndRegistration();

                // after all queries were created and registered, they must be
                // reset so the buffers reference no record.
                Set<QueryOffEndListener> listeners = wa.tm.getOffEndListeners(true);

                for (QueryOffEndListener qoel : listeners)
                {
                   qoel.reset();
                }
             }

             wa.tm.blockSetup();

             blockLabel:
             do
             {
                try
                {
                   processBody(wa, block, on, defOn);
                }

                catch (LegacyErrorException lex)
                {
                   processLegacyException(wa, lex);
                }

                catch (LegacyStopException lex)
                {
                   processLegacyStopException(wa, lex);
                }

                catch (ConditionException ce)
                {
                   wa.tm.notifyCondition(ce);

                   switch (processCondition(wa, on, defOn, ce, enclosing, label))
                   {
                      // note that this is not an iterating block so a leave or
                      // next targeted at this block must always act the same
                      case BREAK:
                      case CONTINUE:
                         break blockLabel;
                      default:
                         break;
                   }
                }

                catch (RetryUnwindException rue)
                {
                   wa.tm.honorRetry(rue);
                }

                catch (LeaveUnwindException lue)
                {
                   if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the LEAVE targeted this block or an enclosing
                      // non-managed block
                      break blockLabel;
                   }

                   // the LEAVE must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw lue;
                }

                catch (NextUnwindException nue)
                {
                   if (testNext(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the NEXT can't be targeted at this block BUT it can be
                      // targeted at an enclosing non-managed block
                      break blockLabel;
                   }

                   // the NEXT must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw nue;
                }

                catch (ReturnUnwindException rue)
                {
                   // RETURN can't be targeted at a DO block so keep unwinding
                   throw rue;
                }

                catch (Throwable thr)
                {
                   wa.tm.abnormalEnd(thr);
                }
             }
             while (wa.tm.needsRetry());
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Execute a a termination block like CATCH and FINALLY, emulating {@link #doBlockWorker}.
        *
        * @param    wa
        *           The {@link WorkArea} instance.
        * @param    lvl
        *           The transaction level to be honored.
        * @param    label
        *           The block name of the current block.
        * @param    finBlock
        *           Flag identifying a FINALLY block when <code>true</code> and a CATCH block otherwise.
        * @param    block
        *           The code to execute.
        */
       private static void doTerminationBlockWorker(WorkArea        wa,
                                                    TransactionType lvl,
                                                    String          label,
                                                    boolean         finBlock,
                                                    Block           block)
       {
          String[] enclosing = null;
          OnPhrase[] on = null;

          // give the block a chance to handle any initialization which must happen BEFORE the TM scope is pushed;
          // doesn't repeat on retry
          block.pre();

          BlockType blockType = finBlock ? BlockType.FINALLY : BlockType.DO;

          int ttype = convertTransType(lvl, blockType);

          OnPhrase[] defOn = null;

          if (lvl == TransactionType.FULL)
          {
             defOn = new OnPhrase[1];
             defOn[0] = new OnPhrase(Condition.ERROR, Action.RETRY, label);
          }

          int props = decodeConditions(defOn, on);

          if (wa == null)
          {
             wa = work.obtain();
          }

          wa.tm.pushScope(label, ttype, props, false, false, false, false, blockType);

          try
          {
             block.init();

             wa.tm.blockSetup();

             // a CATCH or FINALLY block can't be retried
             blockLabel:
             {
                try
                {
                   processBody(wa, block, on, defOn);
                }

                catch (LegacyErrorException lex)
                {
                   processLegacyException(wa, lex);
                }

                catch (LegacyStopException lex)
                {
                   processLegacyStopException(wa, lex);
                }

                catch (ConditionException ce)
                {
                   wa.tm.notifyCondition(ce);

                   switch (processCondition(wa, on, defOn, ce, enclosing, label))
                   {
                      // note that this is not an iterating block so a leave or
                      // next targeted at this block must always act the same
                      case BREAK:
                      case CONTINUE:
                         break blockLabel;
                      default:
                         break;
                   }
                }

                catch (RetryUnwindException rue)
                {
                   wa.tm.honorRetry(rue);
                }

                catch (LeaveUnwindException lue)
                {
                   if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the LEAVE targeted this block or an enclosing
                      // non-managed block
                      break blockLabel;
                   }

                   // the LEAVE must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw lue;
                }

                catch (NextUnwindException nue)
                {
                   if (testNext(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the NEXT can't be targeted at this block BUT it can be
                      // targeted at an enclosing non-managed block
                      break blockLabel;
                   }

                   // the NEXT must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw nue;
                }

                catch (ReturnUnwindException rue)
                {
                   // RETURN can't be targeted at a DO block so keep unwinding
                   throw rue;
                }

                catch (Throwable thr)
                {
                   wa.tm.abnormalEnd(thr);
                }
             }
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Execute a DO WHILE expression, DO TO var = val1 to val2 by val3 or DO
        * TO WHILE expression loop with the given configuration and no default
        * properties.  At least one of the to clause or while expression must be
        * passed and it is valid to have both passed in which case both of the
        * conditions are tested with a logical AND.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       private static void doLoopWorker(TransactionType lvl,
                                        String[]        enclosing,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          BlockType btype = null;
          boolean   next  = false;

          if (to == null)
          {
             if (expr == null)
             {
                throw new IllegalStateException("DO loop MUST have a TO or WHILE clause.");
             }
             else
             {
                btype = BlockType.DO_WHILE;
             }
          }
          else
          {
             btype = (expr == null) ? BlockType.DO_TO : BlockType.DO_TO_WHILE;
             next  = true;
          }

          OnPhrase[] defOn = null;

          if (lvl == TransactionType.FULL)
          {
             defOn = new OnPhrase[1];
             defOn[0] = new OnPhrase(Condition.ERROR, Action.RETRY, label);
          }

          // process the loop
          coreLoop(btype, next, lvl, enclosing, label, to, expr, on, defOn, block);
       }

       /**
        * Execute a REPEAT, REPEAT WHILE expression, REPEAT TO var = val1 to val2
        * by val3 or REPEAT TO WHILE expression loop with the given configuration
        * and with default properties.  If neither the to clause or while
        * expression is specified, this is an infinite loop. If both are specified
        * then both of the conditions are tested with a logical AND. By default,
        * the ON ENDKEY UNDO, LEAVE and ON ERROR UNDO, RETRY properties are
        * supported.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       private static void repeatWorker(TransactionType lvl,
                                        String[]        enclosing,
                                        String          label,
                                        ToClause        to,
                                        LogicalOp       expr,
                                        OnPhrase[]      on,
                                        Block           block)
       {
          BlockType btype = null;
          boolean next = false;

          if (to == null)
          {
             btype = (expr == null) ? BlockType.REPEAT : BlockType.REPEAT_WHILE;
          }
          else
          {
             btype = (expr == null) ? BlockType.REPEAT_TO : BlockType.REPEAT_TO_WHILE;
             next  = true;
          }

          OnPhrase[] defOn = new OnPhrase[2];
          defOn[0] = new OnPhrase(Condition.ENDKEY, Action.LEAVE, label);
          defOn[1] = new OnPhrase(Condition.ERROR, Action.RETRY, label);

          // process the loop
          coreLoop(btype, next, lvl, enclosing, label, to, expr, on, defOn, block);
       }

       /**
        * Execute a DO or REPEAT loop with all possible loop constructs, the
        * given configuration and with default properties.
        *
        * @param    btype
        *           Current block type.
        * @param    next
        *           <code>true</code> if on infinite loop protection a retry
        *           should be converted to a NEXT, <code>false</code> to convert
        *           to a LEAVE.
        * @param    lvl
        *           The transaction level to be honored.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        * @param    on
        *           List of user-defined on phrases.
        * @param    defOn
        *           List of default properties for the block. Use
        *           <code>null</code> to indicate no default properties for the
        *           block.
        * @param    block
        *           The code to execute.
        */
       private static void coreLoop(BlockType       btype,
                                    boolean         next,
                                    TransactionType lvl,
                                    String[]        enclosing,
                                    String          label,
                                    ToClause        to,
                                    LogicalOp       expr,
                                    OnPhrase[]      on,
                                    OnPhrase[]      defOn,
                                    Block           block)
       {
          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();

          int ttype = convertTransType(lvl, btype);
          int props = decodeConditions(defOn, on);

          WorkArea wa = work.obtain();

          wa.tm.pushScope(label, ttype, props, false, false, true, next, btype);

          try
          {
             try
             {
                // each constructed query during block initialization will be
                // collected
                wa.tm.startOffEndRegistration();

                // give the block a chance to initialize its state and don't
                // repeat that during iteration or retry
                block.init();
             }
             finally
             {
                wa.tm.stopOffEndRegistration();

                // after all queries were created and registered, they must be
                // reset so the buffers reference no record.
                Set<QueryOffEndListener> listeners = wa.tm.getOffEndListeners(true);

                if (!listeners.isEmpty())
                {
                   for (QueryOffEndListener qoel : listeners)
                   {
                      qoel.reset();
                   }
                }
             }

             loop:
             while (needsIterate(to, expr))
             {
                wa.tm.blockSetup();

                do
                {
                   try
                   {
                      processBody(wa, block, on, defOn);
                   }

                   catch (LegacyErrorException lex)
                   {
                      processLegacyException(wa, lex);
                   }

                   catch (LegacyStopException lex)
                   {
                      processLegacyStopException(wa, lex);
                   }

                   catch (ConditionException ce)
                   {
                      wa.tm.notifyCondition(ce);

                      switch (processCondition(wa, on, defOn, ce, enclosing, label))
                      {
                         case BREAK:
                            break loop;
                         case CONTINUE:
                            continue loop;
                         default:
                            break;
                      }
                   }

                   catch (RetryUnwindException rue)
                   {
                      wa.tm.honorRetry(rue);
                   }

                   catch (LeaveUnwindException lue)
                   {
                      if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                      {
                         // the LEAVE targeted this block or an enclosing
                         // non-managed block
                         break loop;
                      }

                      // the LEAVE must be referencing an enclosing block which IS
                      // known to the block manager OR to one of the other
                      // enclosing managed blocks, so keep unwinding the stack
                      throw lue;
                   }

                   catch (NextUnwindException nue)
                   {
                      switch (testNext(wa, enclosing, label))
                      {
                         case BREAK:
                            // the NEXT is targeted at an enclosing non-managed block
                            break loop;

                         case CONTINUE:
                            // the NEXT is targeted at the current loop
                            continue loop;

                         default:
                            break;
                      }

                      // the NEXT must be referencing an enclosing block which IS
                      // known to the block manager OR to one of the other
                      // enclosing managed blocks, so keep unwinding the stack
                      throw nue;
                   }

                   catch (ReturnUnwindException rue)
                   {
                      // RETURN can't be targeted at a DO loop so keep unwinding
                      throw rue;
                   }

                   catch (Throwable thr)
                   {
                      wa.tm.abnormalEnd(thr);
                   }
                }
                while (wa.tm.needsRetry());

                if (wa.tm.isBreakPending())
                {
                   break loop;
                }
             }
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Execute a FOR FIRST/LAST WHILE block, FOR FIRST/LAST TO block
        * or FOR FIRST/LAST TO WHILE block with the given configuration and
        * with default properties.  Any TO or WHILE clause is treated as an
        * additional condition that must be met before the block body is executed.
        * Note that the presence of a TO or WHILE does not make this a loop. If
        * neither the TO clause or WHILE expression is specified, this is a
        * simple block. If both are specified then both of the conditions are
        * tested with a logical AND. By default, the ON ENDKEY UNDO, LEAVE and ON
        * ERROR UNDO, RETRY properties are supported.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself or if there
        * is a TO or WHILE clause then the query processing should be located in
        * the {@link Block#enter} method.  This means that the caller is
        * responsible for all query processing. The record retrieval must be done
        * on the first line of code in the block or in the <code>enter</code>
        * method to duplicate the Progress behavior. Note that this is required
        * to handle all error cases and 4GL conditions properly.
        * <p>
        * The evaluation of the TO or WHILE block termination conditions is done
        * AFTER the record retrieval.  This causes any found record to remain
        * available if the block is never entered because of the TO or WHILE
        * conditions.
        *
        * @param    lvl
        *           The transaction level to be honored.
        * @param    query
        *           query that will iterate forBlock.
        * @param    direction
        *           direction in which query will be iterating.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines the block condition. The block
        *           control variable is initialized before entering the block.
        *           Before the block body is entered, the control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at that moment). if the termination condition is
        *           met, the block is never entered.
        * @param    expr
        *           The WHILE clause that defines a block condition. This
        *           expression is evaluated before the block body is about to
        *           be entered.  The block body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       private static void forBlockWorker(TransactionType lvl,
                                          P2JQuery        query,
                                          int             direction,
                                          String[]        enclosing,
                                          String          label,
                                          ToClause        to,
                                          LogicalOp       expr,
                                          OnPhrase[]      on,
                                          Block           block)
       {
          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();
          query.setLenientOffEnd(true);

          BlockType btype = null;

          if (to == null)
          {
             btype = (expr == null) ? BlockType.FOR_BLOCK : BlockType.FOR_BLOCK_WHILE;
          }
          else
          {
             btype = (expr == null) ? BlockType.FOR_BLOCK_TO : BlockType.FOR_BLOCK_TO_WHILE;
          }

          OnPhrase[] defOn = new OnPhrase[2];
          defOn[0] = new OnPhrase(Condition.ENDKEY, Action.LEAVE, label);
          defOn[1] = new OnPhrase(Condition.ERROR, Action.RETRY, label);

          int ttype = convertTransType(lvl, btype);
          int props = decodeConditions(defOn, on);

          WorkArea wa = work.obtain();

          wa.tm.pushScope(label, ttype, props, false, false, false, false, btype);

          try
          {
             try
             {
                // each constructed query during block initialization will be
                // collected
                wa.tm.startOffEndRegistration();

                // give the block a chance to initialize its state and don't
                // repeat that during retry
                block.init();
             }
             finally
             {
                // after block initialization is finished, the off end listeners
                // for all the buffers in the collected queries are saved
                wa.tm.stopOffEndRegistration();
             }

             wa.tm.blockSetup();

             blockLabel:
             do
             {
                try
                {
                   boolean querySucceful = false;
                   switch (direction)
                   {
                      case QueryConstants.FIRST: {
                         querySucceful = query.first();
                         break;
                      }
                      case QueryConstants.LAST: {
                         querySucceful = query.last();
                         break;
                      }
                      case QueryConstants.UNIQUE: {
                         querySucceful = query.unique();
                         break;
                      }
                      case QueryConstants.ITERATE: {
                         querySucceful = query.next();
                         break;
                      }
                   }

                   if (!querySucceful)
                   {
                      wa.tm.notifyCondition(Condition.ENDKEY);
                      try
                      {
                         wa.tm.processOffEndListeners(true);
                         // avoid roll-back; the query initialization might have done some database work
                         // like honoring the RecordNursery. If the query didn't find any record, using a rollback
                         // will eliminate the work done in the init block (i.e. a side-effect aggressive flush).
                         break blockLabel;
                      }
                      finally
                      {
                         wa.tm.processOffEndListeners(false);
                      }
                   }

                   if (processForBody(wa, block, to, expr, on, defOn))
                   {
                      break blockLabel;
                   }
                }

                catch (ConditionException ce)
                {
                   wa.tm.notifyCondition(ce);

                   // when there are no more records in the query, we ALWAYS
                   // UNDO, LEAVE (which is the same as the default ENDKEY
                   // processing) the current block even if the user has defined
                   // an explicit behavior for ENDKEY
                   if (ce instanceof QueryOffEndException)
                   {
                      QueryOffEndException qoee = (QueryOffEndException) ce;
                      QueryOffEndListener[] listeners = qoee.getListeners();

                      // flag indicating if the off-end listeners are the one
                      // registered during block initialization
                      boolean allOffEndListeners = true;
                      for (int i = 0; i < listeners.length; i++)
                      {
                         allOffEndListeners = allOffEndListeners &&
                                              wa.tm.isOffEndListener(listeners[i]);
                      }

                      if (allOffEndListeners)
                      {
                         try
                         {
                            // if the buffers are the ones used by the FOR block,
                            // process them and trigger an UNDO, LEAVE
                            wa.tm.processOffEndListeners(true);

                            wa.tm.rollback(label, ce);
                            break blockLabel;
                         }
                         finally
                         {
                            wa.tm.processOffEndListeners(false);
                         }
                      }
                   }

                   try
                   {
                      // if the exception was triggered by something else, then
                      // the off-end interested buffers must remain on the
                      // currently referenced record
                      wa.tm.processOffEndListeners(true);

                      // normal condition processing
                      switch (processCondition(wa, on, defOn, ce, enclosing, label))
                      {
                         // note that this is not an iterating block so a leave or
                         // next targeted at this block must always act the same
                         case BREAK:
                         case CONTINUE:
                            break blockLabel;
                         default:
                            break;
                      }
                   }
                   finally
                   {
                      wa.tm.processOffEndListeners(false);
                   }
                }

                catch (RetryUnwindException rue)
                {
                   wa.tm.honorRetry(rue);
                }

                catch (LeaveUnwindException lue)
                {
                   if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the LEAVE targeted this block or an enclosing
                      // non-managed block
                      break blockLabel;
                   }

                   // the LEAVE must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw lue;
                }

                catch (NextUnwindException nue)
                {
                   if (testNext(wa, enclosing, label) == Disposition.BREAK)
                   {
                      // the NEXT can't be targeted at this block BUT it can be
                      // targeted at an enclosing non-managed block
                      break blockLabel;
                   }

                   // the NEXT must be referencing an enclosing block which IS
                   // known to the block manager OR to one of the other enclosing
                   // managed blocks, so keep unwinding the stack
                   throw nue;
                }

                catch (ReturnUnwindException rue)
                {
                   // RETURN can't be targeted at a DO block so keep unwinding
                   throw rue;
                }

                catch (Throwable thr)
                {
                   wa.tm.abnormalEnd(thr);
                }
             }
             while (wa.tm.needsRetry());
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Execute a FOR EACH, FOR EACH WHILE block, FOR EACH TO block
        * or FOR EACH TO WHILE block with the given configuration and
        * with default properties.  Any TO or WHILE clause is treated as an
        * additional condition that must be met before the loop body is executed.
        * If both are specified then both of the conditions are tested with a
        * logical AND. By default, the ON ENDKEY UNDO, LEAVE and ON ERROR UNDO,
        * RETRY properties are supported.
        * <p>
        * The record retrieval that is associated with FOR blocks or loops must
        * be implemented directly inside the code of the block itself or if there
        * is a TO or WHILE clause then the query processing should be located in
        * the {@link Block#enter} method.  This means that the caller is
        * responsible for all query processing. The record retrieval must be done
        * on the first line of code in the block or in the <code>enter</code>
        * method to duplicate the Progress behavior. Note that this is required
        * to handle all error cases and 4GL conditions properly.
        * <p>
        * The evaluation of the TO or WHILE block termination conditions is done
        * AFTER the record retrieval.  This causes any found record to remain
        * available if the loop is never entered (or re-entered) because of the
        * TO or WHILE conditions.
        *
        * @param    lvl
        *           The transaction level to be honored.
        *           @param    query
        *           query that will iterate forEachBlock.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>.
        * @param    on
        *           List of user-defined on phrases.
        * @param    block
        *           The code to execute.
        */
       private static void forEachWorker(TransactionType lvl,
                                         P2JQuery        query,
                                         String[]        enclosing,
                                         String          label,
                                         ToClause        to,
                                         LogicalOp       expr,
                                         OnPhrase[]      on,
                                         Block           block)
       {
          // give the block a chance to handle any initialization which must happen BEFORE the TM
          // scope is pushed; doesn't repeat on retry
          block.pre();
          query.setLenientOffEnd(true);
          query.setIterating(true);

          BlockType btype = null;

          if (to == null)
          {
             btype = (expr == null) ? BlockType.FOR_LOOP : BlockType.FOR_LOOP_WHILE;
          }
          else
          {
             btype = (expr == null) ? BlockType.FOR_LOOP_TO : BlockType.FOR_LOOP_TO_WHILE;
          }

          OnPhrase[] defOn = new OnPhrase[2];
          defOn[0] = new OnPhrase(Condition.ENDKEY, Action.LEAVE, label);
          defOn[1] = new OnPhrase(Condition.ERROR, Action.RETRY, label);

          int ttype = convertTransType(lvl, btype);
          int props = decodeConditions(defOn, on);

          WorkArea wa = work.obtain();

          wa.tm.pushScope(label, ttype, props, false, false, true, true, btype);

          try
          {
             try
             {
                // each constructed query during block initialization will be
                // collected
                wa.tm.startOffEndRegistration();

                // give the block a chance to initialize its state and don't
                // repeat that during retry
                block.init();
             }
             finally
             {
                // after block initialization is finished, the off end listeners
                // for all the buffers in the collected queries are saved
                wa.tm.stopOffEndRegistration();
                // after all queries were created and registered, they must be
                // reset so the buffers reference no record.
                if (!query.isPresort())
                {
                   Set<QueryOffEndListener> listeners = wa.tm.getOffEndListeners(false);

                   for (QueryOffEndListener qoel : listeners)
                   {
                      qoel.reset();
                   }
                }
             }

             boolean topQuerySuccessful;
             loop:
             while (true)
             {
                wa.tm.blockSetup();
                topQuerySuccessful = false;

                do
                {
                   try
                   {
                      if (!query.next())
                      {
                         wa.tm.notifyCondition(Condition.ENDKEY);
                         try
                         {
                            wa.tm.processOffEndListeners(true);
                            // avoid roll-back; the query initialization might have done some database work
                            // like honoring the RecordNursery. If the query didn't find any record, using a rollback
                            // will eliminate the work done in the init block (i.e. a side-effect aggressive flush).
                            break loop;
                         }
                         finally
                         {
                            wa.tm.processOffEndListeners(false);
                         }
                      }
                      topQuerySuccessful = true;

                      if (processForBody(wa, block, to, expr, on, defOn))
                      {
                         break loop;
                      }
                   }

                   catch (ConditionException ce)
                   {
                      if (ce.shouldExitBlock() && !topQuerySuccessful)
                      {
                         // an error was produced when executing the FOR-EACH query
                         // leave the block instead of retrying
                         try
                         {
                            wa.tm.processOffEndListeners(true);
                            break loop;
                         }
                         finally
                         {
                            wa.tm.processOffEndListeners(false);
                         }
                      }

                      wa.tm.notifyCondition(ce);

                      if (ce instanceof QueryOffEndException)
                      {
                         QueryOffEndException qoee = (QueryOffEndException) ce;
                         QueryOffEndListener[] listeners = qoee.getListeners();

                         // flag indicating if the off-end listeners are the one
                         // registered during block initialization
                         boolean allOffEndListeners = true;
                         for (int i = 0; i < listeners.length; i++)
                         {
                            allOffEndListeners = allOffEndListeners &&
                                                 wa.tm.isOffEndListener(listeners[i]);
                         }

                         if (allOffEndListeners)
                         {
                            try
                            {
                               // if the buffers are the ones used by the FOR block,
                               // process them and trigger an UNDO, LEAVE
                               wa.tm.processOffEndListeners(true);

                               wa.tm.rollback(label, ce);
                               break loop;
                            }
                            finally
                            {
                               wa.tm.processOffEndListeners(false);
                            }
                         }
                      }

                      try
                      {
                         // if the exception was triggered by something else, then
                         // the off-end interested buffers must remain on the
                         // currently referenced record
                         wa.tm.processOffEndListeners(true);

                         // normal condition processing
                         switch (processCondition(wa, on, defOn, ce, enclosing, label))
                         {
                            case BREAK:
                               break loop;
                            case CONTINUE:
                               continue loop;
                            default:
                               break;
                         }
                      }
                      finally
                      {
                         wa.tm.processOffEndListeners(false);
                      }
                   }

                   catch (RetryUnwindException rue)
                   {
                      wa.tm.honorRetry(rue);
                   }

                   catch (LeaveUnwindException lue)
                   {
                      if (testLeave(wa, enclosing, label) == Disposition.BREAK)
                      {
                         // the LEAVE targeted this block or an enclosing non-managed block
                         break loop;
                      }

                      // the LEAVE must be referencing an enclosing block which IS
                      // known to the block manager OR to one of the other
                      // enclosing managed blocks, so keep unwinding the stack
                      throw lue;
                   }

                   catch (NextUnwindException nue)
                   {
                      switch (testNext(wa, enclosing, label))
                      {
                         case BREAK:
                            // the NEXT is targeted at an enclosing non-managed block
                            break loop;

                         case CONTINUE:
                            // the NEXT is targeted at the current loop
                            continue loop;

                         default:
                            break;
                      }

                      // the NEXT must be referencing an enclosing block which IS
                      // known to the block manager OR to one of the other
                      // enclosing managed blocks, so keep unwinding the stack
                      throw nue;
                   }

                   catch (ReturnUnwindException rue)
                   {
                      // RETURN can't be targeted at a DO block so keep unwinding
                      throw rue;
                   }

                   catch (Throwable thr)
                   {
                      wa.tm.abnormalEnd(thr);
                   }
                }
                while (wa.tm.needsRetry());

                if (wa.tm.isBreakPending())
                {
                   break loop;
                }
             }
          }

          finally
          {
             wa.tm.popScope();
          }
       }

       /**
        * Test the given expressions to determine if the calling loop should
        * iterate or if the loop should exit.  Either or both parameters
        * may be <code>null</code> individually or simultaneously.
        *
        * @param    to
        *           The TO clause that defines a loop condition. The loop control
        *           variable is initialized on the first pass through and on
        *           subsequent passes it is incremented by a given factor. Before
        *           the loop body is entered, the loop control variable is
        *           compared to the termination value (which is dynamically
        *           resolved at each loop iteration). When the termination
        *           condition is met, the loop ends. If this is <code>null</code>,
        *           then a WHILE clause MUST be present to provide the condition
        *           for maintaining the loop.
        * @param    expr
        *           The WHILE clause that defines a loop condition. This
        *           expression is evaluated every time the loop body is about to
        *           be entered.  The loop body will be entered unless the
        *           expression evaluates to <code>false</code>. If this is
        *           <code>null</code>, then a TO clause MUST be present to
        *           provide the condition for maintaining the loop.
        *
        * @return   <code>true</code> if all non-null parameters evaluate to
        *           <code>true</code> or if both parameters are <code>null</code>.
        */
       private static boolean needsIterate(ToClause to, LogicalOp expr)
       {
          // in a TO WHILE case (where both conditions are specified), the 4GL evaluates the TO condition first
          // and then conditionally evaluates the WHILE if needed; the use of && here intentionally
          // short-circuits the WHILE expression if the TO is false
          return (to == null || to.incrementAndTest()) && (expr == null || expr.evaluate().booleanValue());
       }

       /**
        * Check if any CATCH blocks defined at the current enclosing block can manage this exception.
        * <p>
        * If none found, ignore this exception.  4GL doesn't seem to propagate the errors further than
        * then current block.
        * <p>
        * If a CATCH block is found, then execute it.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    lex
        *           The thrown legacy error.
        * @param    on
        *           List of user-defined ON phrases.  May be {@code null}.
        * @param    defOn
        *           List of implicit ON phrases for this block.  May be {@code null}.
        *
        * @throws   LegacyErrorException
        *           If the processing needs to be deferred.
        */
       private static void processLegacyError(WorkArea wa, LegacyErrorException lex, OnPhrase[] on, OnPhrase[] defOn)
       {
          ObjectVar<? extends LegacyError> error = lex.getError();
          if (error.isUnknown())
          {
             return;
          }

          boolean implicit = (on == null);
          if (implicit)
          {
             on = defOn;
          }

          LegacyError legacyError = error.ref;
          Class<?> errCls = legacyError.getClass();

          boolean isFromReturn = wa.tm.getBlock().wasReturnError;
          boolean mustManage = mustManageLegacyError(wa);
          // do not throw if we are exiting a top-level block
          boolean canThrow = mustManage || isFromReturn || (lex.isExplicit() && !wa.tm.isTopLevelBlock());
          boolean noThrowOnError = false;
          if (on != null && wa.tm.hasErrorProp() && (!implicit || !mustManage))
          {
             OnPhrase imple = matchCondition(on, null, Condition.ERROR);
             if (imple != null)
             {
                canThrow = canThrow || (imple.action == Action.THROW);
                noThrowOnError = (imple.action != Action.THROW);
             }
          }

          int i = 0;
          int topLvlBlocks = 0;
          BlockDefinition block = wa.tm.getBlock(i);
          if (isFromReturn)
          {
             // skip all CATCH blocks from current top-level block
             while (block != null && !block.topLevel)
             {
                i = i + 1;
                block = wa.tm.getBlock(i);
             }
             if (block != null)
             {
                i = i + 1;
                block = wa.tm.getBlock(i);
             }

             lex.setFromReturn(false);
          }
          while (block != null)
          {
             topLvlBlocks += (block.topLevel ? 1 : 0);

             if (block.catchBlocks != null)
             {
                for (Class<?> cls : block.catchBlocks.keySet())
                {
                   if (cls.isAssignableFrom(errCls))
                   {
                      if (!canThrow && topLvlBlocks > 1)
                      {
                         displayErrorMessage(wa.tm, legacyError, 1, true, true, false);

                         // we need a decrement here, as the instance is also 'hooked' by LegacyErrorException
                         error.decrement();

                         // release the reference
                         error.set(null);

                         return;
                      }
                      if (i == 0)
                      {
                         BlockDefinition blk = block;
                         String label = blk.label;
                         wa.tm.setupCatchProcessing(() ->
                         {
                            try
                            {
                               // clear any pending errors
                               wa.tm.errHlp.clearPending();
                               Block catchBlock = new Block()
                               {
                                  @Override
                                  public void body()
                                  {
                                     wa.tm.getBlock().type = BlockType.CATCH;
                                     blk.catchBlocks.get(cls).accept(error);
                                  }
                               };
                               doTerminationBlockWorker(wa,
                                                        TransactionType.NONE,
                                                        CATCH_BLOCK_LABEL + label,
                                                        false,
                                                        catchBlock);
                            }
                            finally
                            {
                               // we need a decrement here, as the instance is also 'hooked' by LegacyErrorException
                               error.decrement();

                               // release this reference
                               error.set(null);
                            }
                         });

                         // the error was registered, will be processed in popScope, undo and leave the block
                         undoLeave("", "");
                         return;
                      }
                      else if (noThrowOnError)
                      {
                         throw new ErrorConditionException(error.ref.getMessage(new integer(1)).toStringMessage());
                      }
                      else if (canThrow)
                      {
                         // this is re-thrown, so mark it as 'explicit'
                         lex.setExplicit(true);
                         throw lex;
                      }
                   }
                }
             }

             i = i + 1;
             block = wa.tm.getBlock(i);
          }

          if (noThrowOnError)
          {
             throw new ErrorConditionException(error.ref.getMessage(new integer(1)).toStringMessage());
          }

          if (canThrow)
          {
             displayErrorMessages(wa.tm, legacyError, false, true);
             throw lex;
          }

          // release it was not found, and is from a RETURN ERROR statement
          if (isFromReturn)
          {
             if (ErrorManager.isPending())
             {
                throw lex;
             }
             displayErrorMessage(wa.tm, legacyError, 1, true, true, false);
          }
          else
          {
             displayErrorMessages(wa.tm, legacyError, true, false);
          }

          // we need a decrement here, as the instance is also 'hooked' by LegacyErrorException
          error.decrement();

          // release the reference
          error.set(null);

          if (lex.isFromReturn())
          {
             leave(wa, "");
          }
       }

       /**
        * Returns if the legacy error needs to be displayed based on several criteria: if the error has already
        * been displayed, if this is part of the top block execution and if it's a silent block (suppressed
        * error).
        *
        * @param    tm
        *           The transaction helper with information about the block.
        * @param    legacyError
        *           The error to be displayed.
        *
        * @return   See above.
        */
       private static boolean shouldDisplayError(TransactionHelper tm, LegacyError legacyError)
       {
          return !legacyError._isDisplayed() && tm.isTopLevelBlock() && !tm.isSuppressError();
       }

       /**
        * Displays all messages of the legacy error if it is eligible for display, and then marks the error as
        * displayed.
        *
        * @param    tm
        *           The transaction helper with information about the block.
        * @param    legacyError
        *           The error to be displayed.
        * @param    addCallStack
        *           Flag to indicate if callstack needs to be added to the message.
        * @param    onlyLog
        *           Flag to record a log instead of displaying the error.
        */
       private static void displayErrorMessages(TransactionHelper tm,
                                                LegacyError legacyError,
                                                boolean addCallStack,
                                                boolean onlyLog)
       {
          if (!shouldDisplayError(tm, legacyError))
          {
             return;
          }
          for (int i = 0; i < legacyError.getNumMessages().intValue(); i++)
          {
             displayErrorMessage(tm, legacyError, i + 1, false, addCallStack, onlyLog);
          }
          legacyError._setDisplayed();
       }

       /**
        * Displays the message on the selected index of the legacy error, if the error is eligible for display,
        * and marks the error as displayed, if needed.
        *
        * @param    tm
        *           The transaction helper with information about the block.
        * @param    legacyError
        *           The error to be displayed.
        * @param    markDisplayed
        *           Flag to indicate if the error should be marked as displayed.
        * @param    addCallStack
        *           Flag to indicate if callstack needs to be added to the message.
        * @param    onlyLog
        *           Flag to record a log instead of displaying the error.
        */
       private static void displayErrorMessage(TransactionHelper tm,
                                               LegacyError legacyError,
                                               int msgIndex,
                                               boolean markDisplayed,
                                               boolean addCallStack,
                                               boolean onlyLog)
       {
          character errMsg = legacyError.getMessage(new integer(msgIndex));
          String errMsgString = errMsg.toJavaType();

          if (!StringHelper.hasContent(errMsgString) || !shouldDisplayError(tm, legacyError))
          {
             return;
          }

          if (markDisplayed)
          {
             legacyError._setDisplayed();
          }

          if (onlyLog)
          {
             ErrorManager.writeLog(errMsgString);
          }
          else if (addCallStack)
          {
             ErrorManager.displayError(errMsgString);
          }
          else
          {
             ErrorManager.displayError(errMsgString, false, null, false);
          }
       }

       /**
        * Check if any CATCH blocks defined at the current enclosing block can manage thisSTOP exception.
        * <p>
        * If a CATCH block is found, then execute it.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    lex
        *           The thrown legacy error.
        *
        * @throws   LegacyErrorException
        *           If the processing needs to be deferred.
        */
       private static void processLegacyStop(WorkArea wa, LegacyStopException lex)
       {
          ObjectVar<? extends Stop> error = lex.getError();
          if (error.isUnknown())
          {
             return;
          }

          Stop legacyStop = error.ref;
          Class<?> stopCls = legacyStop.getClass();

          boolean mustManage = mustManageLegacyStop(wa);
          // do not throw if we are exiting a top-level block
          boolean canThrow = mustManage;
          boolean noThrowOnError = !mustManage;

          int i = 0;
          BlockDefinition block = wa.tm.getBlock(i);

          while (block != null)
          {
             if (block.catchBlocks != null)
             {
                for (Class<?> cls : block.catchBlocks.keySet())
                {
                   if (cls.isAssignableFrom(stopCls))
                   {
                      if (i == 0)
                      {
                         BlockDefinition blk = block;
                         wa.tm.setupCatchProcessing(() ->
                         {
                            // clear any pending errors
                            wa.tm.errHlp.clearPending();

                            Block catchBlock = new Block()
                            {
                               @Override
                               public void body()
                               {
                                  wa.tm.getBlock().type = BlockType.CATCH;
                                  blk.catchBlocks.get(cls).accept(error);
                               }
                            };
                            doTerminationBlockWorker(wa,
                                                     TransactionType.NONE,
                                                     CATCH_BLOCK_LABEL,
                                                     false,
                                                     catchBlock);
                         });

                         if (error.ref instanceof StopAfter)
                         {
                            wa.tm.setupStopAfterProccessing(lex);
                         }

                         // the error was registered, will be processed in popScope, undo and leave the block
                         undoLeave("", "");
                         return;
                      }
                      else if (noThrowOnError)
                      {
                         throw new StopConditionException("Thread was asynchronously interupted");
                      }
                      else if (canThrow)
                      {
                         // this is re-thrown, so mark it as 'explicit'
                         throw lex;
                      }
                   }
                }
             }

             i = i + 1;
             block = wa.tm.getBlock(i);
          }

          // we need a decrement here, as the instance is also 'hooked' by LegacyErrorException
          error.decrement();

          // release the reference
          error.set(null);

          throw new StopConditionException("Thread was asynchronously interupted");
       }

       /**
        * Check if any CATCH blocks defined at the specified enclosing block can manage this exception.
        * <p>
        * If none found, ignore this exception.  4GL doesn't seem to propagate the errors further than
        * then current block.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in caller.
        * @param    type
        *           The error type to process.
        * @param    levels
        *           Flag indicating which block to use (0 for current, 1 for parent, etc).  Use -1 to search the
        *           entire stack.
        *
        * @return   <code>true</code> if this exception can be processed by the current block.
        */
       private static boolean hasLegacyError(WorkArea                     wa,
                                             Class<? extends LegacyError> type,
                                             int                          levels)
       {
          if (wa == null)
          {
             wa = work.obtain();
          }

          for (int i = (levels == -1 ? 0 : levels); i <= (levels == -1 ? wa.tm.getNestingLevel() - 1 : levels); i++)
          {
             BlockDefinition block = wa.tm.getBlock(i);

             // Note: block can be null when this method is called from JUnit
             if (block == null || block.catchBlocks == null || block.catchBlocks.isEmpty())
             {
                continue;
             }

             for (Class<?> cls : block.catchBlocks.keySet())
             {
                if (cls.isAssignableFrom(type))
                {
                   return true;
                }
             }
          }

          return false;
       }

       /**
        * Check if any CATCH blocks defined at the specified enclosing block can manage this STOP exception.
        * <p>
        * If none found, on the path upward. But a ON STOP phrase is found of the block, then it takes precedence.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in caller.
        * @param    type
        *           The error type to process.
        * @param    levels
        *           Flag indicating which block to use (0 for current, 1 for parent, etc).  Use -1 to search the
        *           entire stack.
        *
        * @return   <code>true</code> if this exception can be processed by the current block.
        */
       private static boolean hasLegacyStop(WorkArea              wa,
                                            Class<? extends Stop> type)
       {
          if (wa == null)
          {
             wa = work.obtain();
          }

          boolean throwInCatch = wa.tm.getBlock().type == BlockType.CATCH;

          for (int i = throwInCatch ? 2 : 0; i <= wa.tm.getNestingLevel() - 1; i++)
          {
             BlockDefinition block = wa.tm.getBlock(i);

             // Note: block can be null when this method is called from JUnit
             if (block == null || block.catchBlocks == null || block.catchBlocks.isEmpty())
             {
                if (testProps(block.props, Condition.STOP))
                {
                   return false;
                }

                continue;
             }

             for (Class<?> cls : block.catchBlocks.keySet())
             {
                if (type.isAssignableFrom(cls))
                {
                   return true;
                }
             }
          }

          return false;
       }

       /**
        * Make sure that the legacy exception is honoring the roll-back of transactions
        * in the current block. For now, this is not honoring the labeling of undo statements.
        *
        * @param   wa
        *          Context local data or {@code null} if not available in the caller.
        * @param   e
        *          The legacy error exception that caused the unwinding.
        */
       private static void processLegacyException(WorkArea wa, LegacyErrorException e)
       {
          BlockDefinition blk = wa.tm.getBlock();

          if (!blk.undoThrow)
          {
             wa.tm.errHlp.setPending(false);
             wa.tm.attemptRollback();
          }

          blk.undoThrow = false;
          throw e;
       }

       /**
        * Make sure that the legacy stop exception is further thrown.
        *
        * @param   wa
        *          Context local data or {@code null} if not available in the caller.
        * @param   e
        *          The legacy stop exception that caused the unwinding.
        */
       private static void processLegacyStopException(WorkArea wa, LegacyStopException e)
       {
          BlockDefinition blk = wa.tm.getBlock();

          if (!blk.undoThrow)
          {
             wa.tm.attemptRollback();
          }

          blk.undoThrow = false;
          throw e;
       }

       /**
        * Core worker to handle all the possible behavior in response to a
        * condition being raised in an inner block (DO, REPEAT or FOR). The
        * given condition exception will first be matched with the user-defined
        * on phases and then if no match is found, with the default on phrases
        * for the calling block. If nothing is found, then the condition
        * exception will be re-thrown. If a match is found then condition-specific
        * processing will be done to UNDO and then either unwind the stack using
        * exceptions or a disposition will be returned so that the caller can
        * properly implement a LEAVE or NEXT that is targetted at the current
        * block or at an enclosing non-managed block.
        * <p>
        * This honors infinite loop protection for converting NEXT to LEAVE
        * based on runtime state.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    user
        *           List of user-defined on phrases.
        * @param    def
        *           List of default on phrases for the current block type.
        * @param    ce
        *           The condition being raised.
        * @param    enclosing
        *           The list of non-managed block names that enclose the current
        *           block.
        * @param    label
        *           The block name of the current block.
        *
        * @return   If an exception is not thrown (or re-thrown), then the caller
        *           will get a disposition code that should be honored to
        *           properly implement a LEAVE or NEXT action.
        */
       private static Disposition processCondition(WorkArea           wa,
                                                   OnPhrase[]         user,
                                                   OnPhrase[]         def,
                                                   ConditionException ce,
                                                   String[]           enclosing,
                                                   String             label)
       throws ConditionException,
              StackUnwindException,
              RetryUnwindException
       {
          if (def != null                   &&
             (wa.pm.isBlockLevelUndoThrow() ||
              wa.tm.isTopLevelDatabaseTrigger()))
          {
             // change default ERROR, <action> to ERROR, THROW if BLOCK-LEVEL ON ERROR UNDO, THROW
             for (OnPhrase on : def)
             {
                if (on.condition == Condition.ERROR)
                {
                   on.action = Action.THROW;
                }
             }
          }

          Condition current = exceptionToCondition(ce);
          OnPhrase imple    = matchCondition(user, def, current);

          if (imple != null)
          {
             // ERROR processing has a special mode (RETURN ERROR) and STOP
             // processing mode which must unwind the stack to a specific
             // point, so we must check if we are in either of those modes now
             // (before the UNDO or secondary action for the block can be
             // executed)
             if (current == Condition.ERROR)
             {
                ErrorConditionException err = (ErrorConditionException) ce;

                // END-ERROR is propagated to the parent block in blocks that
                // have the ERROR property but do NOT have the ENDKEY property
                if (err.isEndError() && !wa.tm.hasEndkeyProp())
                {
                   // detect the case in which a END-ERROR would have been
                   // converted to ENDKEY, in such a case we must rethrow
                   if (wa.tm.getInteractions() < 2)
                   {
                      // let the parent see this (this will re-throw the
                      // exception after handling rollback state/processing)
                      wa.tm.abnormalEnd(err, false);
                   }
                }

                // if we must unwind, this call will re-throw the exception,
                // otherwise it will return and we can continue with "normal"
                // exception processing
                wa.tm.honorError((ErrorConditionException) ce);
             }
             else if (current == Condition.STOP)
             {
                // if we must unwind, this call will re-throw the exception,
                // otherwise it will return and we can continue with "normal"
                // exception processing
                wa.tm.honorStop((StopConditionException) ce);

                // on stop condition triggered by stop-after timer,
                // right block should be targeted
                StopAfterTimer stopAfterTimer = wa.stopAfterTimer;
                if (stopAfterTimer != null && stopAfterTimer.isStopAfterConditionRaised())
                {
                   if (!stopAfterTimer.isStoppedBlock(wa.tm.getBlock()))
                   {
                      throw ce;
                   }
                   else
                   {
                      stopAfterTimer.cleanUp();
                   }
                }
             }

             // first we UNDO at the specified label (which may be null meaning
             // we UNDO the current block)
             if (imple.condition == Condition.QUIT_COMMIT)
             {
                // let the action proceed without rollback
             }
             else
             {
                wa.tm.rollback(imple.undoLabel);
             }

             Action target = imple.action;

             // honor ILP for NEXT
             if (target == Action.NEXT)
             {
                if (!wa.tm.honorNext(imple.actionLabel))
                {
                   // convert to a LEAVE
                   target = Action.LEAVE;
                }
             }

             // second we implement the specified action
             switch (target)
             {
                case THROW:
                   if (ce instanceof LegacyErrorException)
                   {
                      throw (LegacyErrorException) ce;
                   }
                   else if (ce instanceof ErrorConditionException)
                   {
                      throw (ErrorConditionException) ce;
                   }
                   break;

                case LEAVE:
                   if (imple.actionLabel == null        ||
                       imple.actionLabel.length() == 0  ||
                       imple.actionLabel.equals(label))
                   {
                      return Disposition.BREAK;
                   }
                   else
                   {
                      // at this point we must have a non-null and non-empty
                      // label that is the leave target
                      wa.deferredLeave = imple.actionLabel;

                      if (matches(enclosing, imple.actionLabel))
                      {
                         // the target is a non-managed block that directly
                         // encloses the current block, break out and let the
                         // calling code check to see that this needs to be
                         // honored
                         return Disposition.BREAK;
                      }
                      else
                      {
                         // unwind the stack
                         throw wa.leaveExc;
                      }
                   }
                case NEXT:
                   if (imple.actionLabel == null        ||
                       imple.actionLabel.length() == 0  ||
                       imple.actionLabel.equals(label))
                   {
                      return Disposition.CONTINUE;
                   }
                   else
                   {
                      // at this point we must have a non-null and non-empty
                      // label that is the next target
                      wa.deferredNext = imple.actionLabel;

                      if (matches(enclosing, imple.actionLabel))
                      {
                         // the target is a non-managed block that directly
                         // encloses the current block, break out and let the
                         // calling code check to see that this needs to be
                         // honored
                         return Disposition.BREAK;
                      }
                      else
                      {
                         // unwind the stack
                         throw wa.nextExc;
                      }
                   }
                case RETRY:
                   // if this retry is being triggered by an ENDKEY, remember
                   // that fact so that the retry processing can be customized
                   // (this enables the "stuttering" quirk and some custom
                   // behavior with PAUSE
                   if (current == Condition.ENDKEY)
                   {
                      wa.tm.markEndkeyRetry();
                   }

                   // RETRY is always targetted at the same block as UNDO
                   wa.tm.triggerRetry(imple.undoLabel);

                   return Disposition.NONE;
                case RETURN_NORMAL:
                   // this will throw an exception, it is OK because this method
                   // will always be called in the context of an inner block and
                   // WILL NEVER be called directly from a top-level block
                   returnWorker(wa, imple.value, ReturnType.NORMAL);
                   break;
                case RETURN_CONSUME:
                   // this will throw an exception, it is OK because this method
                   // will always be called in the context of an inner block and
                   // WILL NEVER be called directly from a top-level block
                   returnWorker(wa, imple.value, ReturnType.CONSUME);
                   break;
                case RETURN_ERROR:
                   // this will throw an exception, it is OK because this method
                   // will always be called in the context of an inner block and
                   // WILL NEVER be called directly from a top-level block
                   returnWorker(wa, imple.value, ReturnType.ERROR);
                   break;
                default:
                   break;
             }
          }

          StopAfterTimer stopAfterTimer = wa.stopAfterTimer;
          if (stopAfterTimer != null && stopAfterTimer.isStopAfterConditionRaised())
          {
             if (stopAfterTimer.isStoppedBlock(wa.tm.getBlock()))
             {
                stopAfterTimer.cleanUp();
             }
          }

          // no match so we just re-throw the exception and continue to unwind
          // the stack; but we must process it as an unexpected exception which
          // will maintain rollback state properly
          wa.tm.abnormalEnd(ce, false);

          // never reached because the code above will re-throw the exception
          return null;
       }

       /**
        * Translate exception into {@link Condition} code.
        *
        * @param    ce
        *           Source exception.
        *
        * @return   one of the {@link Condition} codes or <code>null</code> if no
        *           match is found.
        */
       static Condition exceptionToCondition(ConditionException ce)
       {
          Condition current = null;

          if (ce instanceof ErrorConditionException)
          {
             current = Condition.ERROR;
          }
          else if (ce instanceof EndConditionException)
          {
             current = Condition.ENDKEY;
          }
          else if (ce instanceof StopConditionException)
          {
             current = Condition.STOP;
          }
          else if (ce instanceof QuitConditionException)
          {
             current = Condition.QUIT;
          }

          return current;
       }

       /**
        * Find a matching condition in the user-defined on phrases or the default
        * on phrases for the block and return the on phrase that is matched. The
        * user-defined on phrases are searched first and only if there is no
        * match will the default on phrases be searched.
        *
        * @param    user
        *           The set of user-defined on phrases for the current block.
        * @param    def
        *           The set of default on phrases for the current block.
        * @param    cond
        *           The condition being matched.
        *
        * @return   The on phrase that defines the behavior to be implemented or
        *           <code>null</code> if there is no match in either list.
        */
       private static OnPhrase matchCondition(OnPhrase[] user, OnPhrase[] def, Condition cond)
       {
          if (cond == null)
          {
             return null;
          }

          if (user != null)
          {
             for (OnPhrase next : user)
             {
                if (next.condition == cond || (cond == Condition.QUIT && next.condition == Condition.QUIT_COMMIT))
                {
                   return next;
                }
             }
          }

          if (def != null)
          {
             for (OnPhrase next : def)
             {
                if (next.condition == cond)
                {
                   return next;
                }
             }
          }

          return null;
       }

       /**
        * Encode the conditions supported by this block as a bitfield.
        * <p>
        * The inputs are analyzed to match <code>Condition</code> values with
        * their corresponding bits in the <code>TransactionManager</code>
        * properties bitfield.
        * <p>
        * The bits are defined by {@link TransactionManager#PROP_NONE},
        * {@link TransactionManager#PROP_ERROR},
        * {@link TransactionManager#PROP_ENDKEY},
        * {@link TransactionManager#PROP_STOP} or
        * {@link TransactionManager#PROP_QUIT}.
        *
        * @param    user
        *           The set of user-defined on phrases for the current block.
        * @param    def
        *           The set of default on phrases for the current block.
        *
        * @return   The calculated bitmask with each bit set that matches one of
        *           the ON phrase conditions. <code>PROP_NONE</code> will be
        *           returned if both parameters are <code>null</code> and/or
        *           empty.
        */
       private static int decodeConditions(OnPhrase[] user, OnPhrase[] def)
       {
          int bits = PROP_NONE;

          if (user != null)
          {
             for (OnPhrase next : user)
             {
                bits |= conditionMask(next.condition);
             }
          }

          if (def != null)
          {
             for (OnPhrase next : def)
             {
                bits |= conditionMask(next.condition);
             }
          }

          return bits;
       }

       /**
        * Matches a <code>Condition</code> with its corresponding
        * <code>TransactionManager</code> constant.
        *
        * @param    props
        *           The calculated bitmask with each bit set that matches one of
        *           the ON phrase conditions.
        * @param    cond
        *           The condition to match.
        *
        * @return   <code>true</code> if the condition is present in the  bitmask,
        *           <code>false</code> otherwise.
        */
       public static boolean testProps(int props, Condition contition)
       {
          return (props & conditionMask(contition)) != 0;
       }

       /**
        * Matches a <code>Condition</code> with its corresponding
        * <code>TransactionManager</code> constant.
        *
        * @param    cond
        *           The condition to match.
        *
        * @return   The integer constant that represents the given condition.
        */
       private static int conditionMask(Condition cond)
       {
          int rc = PROP_NONE;

          switch (cond)
          {
             case ERROR:
                rc = PROP_ERROR;
                break;
             case ENDKEY:
                rc = PROP_ENDKEY;
                break;
             case STOP:
                rc = PROP_STOP;
                break;
             case QUIT:
                rc = PROP_QUIT;
                break;
             default:
                break;
          }

          return rc;
       }

       /**
        * Detect if the leave event is referencing this block OR if it is
        * referencing a directly enclosing block which is not managed by this
        * class.  In either case, the result will be to break out of the current
        * block.  In all other cases, the result will be to re-throw the exception
        * and cause the stack to unwind to the nearest enclosing managed block.
        * <p>
        * The target of the leave operation must have been stored in context
        * local data when the leave exception was thrown (which caused the
        * stack to unwind).
        * <p>
        * This method is called from within a catch block to determine how to
        * respond to the deferred leave operation for the current block.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    enclosing
        *           The list of non-managed blocks that directly enclose the
        *           current block.
        * @param    label
        *           The name of the current block.  If this matches the target of
        *           the deferred leave operation, then the current block must
        *           be left.
        *
        * @return   Either <code>BREAK</code> or <code>THROW</code>.
        */
       private static Disposition testLeave(WorkArea wa, String[] enclosing, String label)
       {
          // test if the LEAVE is destined for this block
          if (deferredLeaveWorker(wa, label))
          {
             // it is, so honor the LEAVE
             return Disposition.BREAK;
          }
          else
          {
             // handle of LEAVE on an enclosing block that is not one
             // of which the block manager is aware
             if (matches(enclosing, wa.deferredLeave))
             {
                return Disposition.BREAK;
             }
          }

          // the LEAVE must be referencing an enclosing block which IS known
          // to the block manager OR to one of the other enclosing managed
          // blocks, so keep unwinding the stack
          return Disposition.THROW;
       }

       /**
        * Detect if the next event is referencing this block OR if it is
        * referencing a directly enclosing block which is not managed by this
        * class.  In the first case, the result will be to continue the current
        * block.  In the second case, the caller must break out of the current
        * block.  In all other cases, the result will be to re-throw the exception
        * and cause the stack to unwind to the nearest enclosing managed block.
        * <p>
        * The target of the next operation must have been stored in context
        * local data when the next exception was thrown (which caused the
        * stack to unwind).
        * <p>
        * This method is called from within a catch block to determine how to
        * respond to the deferred next operation for the current block.
        *
        * @param    wa
        *           Context local work area.  Must not be {@code null}.
        * @param    enclosing
        *           The list of non-managed blocks that directly enclose the
        *           current block.
        * @param    label
        *           The name of the current block.  If this matches the target of
        *           the deferred leave operation, then the current block must
        *           be left.
        *
        * @return   Either <code>BREAK</code>, <code>CONTINUE</code> or
        *           <code>THROW</code>.
        */
       private static Disposition testNext(WorkArea wa, String[] enclosing, String label)
       {
          // test if the NEXT is destined for this block
          if (deferredNextWorker(wa, label))
          {
             // it is, so honor the NEXT
             return Disposition.CONTINUE;
          }
          else
          {
             // handle of NEXT on an enclosing block that is not one
             // of which the block manager is aware
             if (matches(enclosing, wa.deferredNext))
             {
                return Disposition.BREAK;
             }
          }

          // the NEXT must be referencing an enclosing block which IS known
          // to the block manager OR to one of the other enclosing managed
          // blocks, so keep unwinding the stack
          return Disposition.THROW;
       }

       /**
        * Common worker to cleanup top-level block state just before exiting.
        *
        * @param    wa
        *           The local context.
        */
       private static void exitTopLevel(WorkArea wa)
       {
          wa.topType.pop();
          wa.deferredLeave = null;
          wa.deferredNext  = null;
       }

       /**
        * Preserve certain work area state before running the given code and then restore that state
        * afterward. The code may contain and/or invoke arbitrarily complex code and control flow.
        * Direct invocation (without the state backup/restore) would otherwise corrupt the current
        * work area state.
        *
        * @param    wa
        *           Context local data or {@code null} if not available in the caller.
        * @param    code
        *           The code to execute.
        */
       private static void executeStateManaged(WorkArea wa, Runnable code)
       {
          // preserve current work area state
          ReturnType rtype = wa.rtype;
          String deferredLeave = wa.deferredLeave;
          String deferredNext = wa.deferredNext;
          boolean pendingDynCall = wa.pendingDynCall;

          // set a clean slate for validate processing
          wa.rtype = null;
          wa.deferredLeave = null;
          wa.deferredNext = null;
          wa.pendingDynCall = false;

          try
          {
             code.run();
          }

          finally
          {
             // restore previous state
             wa.rtype = rtype;
             wa.deferredLeave = deferredLeave;
             wa.deferredNext = deferredNext;
             wa.pendingDynCall = pendingDynCall;
          }
       }

       /**
        * Set the return value for the nearest enclosing function. This should only be called if the
        * nearest enclosing top-level block is a {@code FUNCTION}. Multiple calls to this before
        * returning from the function block will cause the value passed on the last call to be
        * honored.
        *
        * @param   bdt
        *          The return value to set. Passing {@code null} will reset the return value to
        *          {@code unknown}.
        * @param   wa
        *          The current context's data or {@code null} to force a lookup of the context data.
        * @param   nearest
        *          The nearest top-level block. Should be a FUNCTION block. Pass {@code null} to
        *          use the context data to find the block.
        */
       private static void setFuncReturn(Object bdt, WorkArea wa, BlockType nearest)
       {
          if (bdt == null)
          {
             return;
          }

          // replace the current latest value with the given instance
          if (wa == null)
          {
             wa = work.obtain();
          }
          if (nearest == null)
          {
             nearest = topLevelType(wa);
          }
          if (nearest == BlockType.FUNCTION)
          {
             if (wa.funcRet.size() > 0)
             {
                wa.funcRet.pop();
                wa.funcRet.push(bdt);

                Class<?> rclass = bdt.getClass();
                if (rclass.isArray() && rclass.getComponentType() == object.class)
                {
                   for (object<?> obj : (object[]) bdt)
                   {
                      if (obj == null || obj.isUnknown())
                      {
                         continue;
                      }

                      _BaseObject_ ref = obj.ref;
                      // mark this object as a pending assign - it will not be implicitly deleted
                      // if it's current referent gets out of scope
                      wa.objHelper.pendingAssign(ref);
                   }
                }
                else if (bdt instanceof object)
                {
                   if (!((object) bdt).isUnknown())
                   {
                      _BaseObject_ ref = ((object) bdt).ref;
                      // mark this object as a pending assign - it will not be implicitly deleted
                      // if it's current referent gets out of scope
                      wa.objHelper.pendingAssign(ref);
                   }
                }
             }
          }
       }

       /**
        * Given a list of strings, detect if the given entry matches (case
        * sensitively) any of the elements in the list.
        *
        * @param    list
        *           The list of strings to check against.
        * @param    entry
        *           The element for which to search.
        *
        * @return   <code>true</code> if the given entry is found in the given
        *           list.
        */
       private static boolean matches(String[] list, String entry)
       {
          if (list == null || entry == null)
             return false;

          for (String element : list)
          {
             if (entry.equalsIgnoreCase(element))
             {
                return true;
             }
          }

          return false;
       }

       /**
        * Helper to convert between this class' enum and the corresponding {@link TransactionManager} constants.
        *
        * @param    ttype
        *           The enum to convert.
        * @param    btype
        *           The block type.
        *
        * @return   The corresponding {@link TransactionManager} constant.
        */
       private static int convertTransType(TransactionType ttype, BlockType btype)
       {
          int newType = -1;

          switch (ttype)
          {
             case NONE:
                newType = NO_TRANSACTION;
                break;
             case SUB:
                newType = SUB_TRANSACTION;
                break;
             case FULL:
                newType = TRANSACTION;
                break;
             default:
                break;
          }

          return newType;
       }

       /**
        * Accesses the type of the nearest enclosing top level block.
        *
        * @param   wa
        *          The current context's data or {@code null} to force a lookup of the context data.
        *
        * @return  The type of the enclosing top level block or {@code null} if there is no top-level
        *          block in the call stack.
        */
       private static BlockType topLevelType(WorkArea wa)
       {
          if (wa == null)
          {
             wa = work.obtain();
          }

          return wa.topType.peek();
       }

       /**
        * Check if we are on the top level of a persistent trigger.
        *
        * @param  wa
        *         The current context's data.
        *
        * @return <code>true</code> if we are on the top level of a persistent trigger
        */
       private static boolean isPersistentTriggerTopLevel(WorkArea wa)
       {
          // The top level of a persistent trigger has the following top-level blocks stack:
          // EXTERNAL_PROC/INTERNAL_PROC and then persistent TRIGGER.

          Iterator<BlockType> iter = wa.topType.iterator();
          if (!iter.hasNext())
          {
             return false;
          }

          BlockType top = iter.next();
          if (top != BlockType.EXTERNAL_PROC &&
              top != BlockType.INTERNAL_PROC)
          {
             return false;
          }

          if (!iter.hasNext() || iter.next() != BlockType.TRIGGER)
          {
             return false;
          }

          return LogicalTerminal.isTopTriggerPersistent();
       }

       /**
        * Update block execution statistics for the given block instance. Depending
        * of the block type, either the class name of the block will be inspected
        * or the call stack will be inspected to determine the block name and then
        * the usage statistics for that block will be incremented.
        *
        * @param    type
        *           The type of the block.
        * @param    block
        *           The block that is about to be executed.
        * @param    start
        *           The start time of the block's execution.
        */
       private static void recordExecutionStats(BlockType type, Block block, long start)
       {
          long end = System.currentTimeMillis();

          // the first application entry in the stack is the one that describes
          // what we are executing
          character sname = EnvironmentOps.getSourceName(1);

          String descr = null;

          // this shouldn't be null, but we will be safe anyway
          if (sname == null)
          {
             descr = "Unknown (call stack analysis failed)";
          }
          else
          {
             descr = sname.toStringMessage();
          }

          // triggers will appear as the same as an external procedure
          if (type == BlockType.TRIGGER ||
              type == BlockType.DATABASETRIGGER)
          {
             // calculate the specific trigger that was executed
             String className = block.getClass().getName();

             int idx = className.lastIndexOf('$');

             if (idx >= 0)
             {
                className = className.substring(idx + 1);
             }

             // append the trigger portion of the class name to the description
             descr = descr + ' ' + className;
          }

          // update the statistics
          AtomicInteger count = stats.get(descr);
          AtomicLong time = times.get(descr);
          if (count == null)
          {
             stats.put(descr, count = new AtomicInteger(0));
             times.put(descr, time = new AtomicLong(0));
          }
          time.addAndGet(end - start);
          count.incrementAndGet();
       }

       /**
        * The CATCH statement.  This API must be called from the Block's init method, and it will
        * register a listener for the specified STOP/ERROR condition.
        * <p>
        * The catch order is the order of this API registration calls.
        *
        * @param    type
        *           The CATCH's error type.
        * @param    catchBlock
        *           The code to be executed for this error.
        */
       private static <T extends _BaseObject_> void registerCatchBlock(Class<T>            type,
                                                                       Consumer<object<T>> catchBlock)
       {
          BlockDefinition block = TransactionManager.getBlock();

          if (block.catchBlocks == null)
          {
             block.catchBlocks = new LinkedHashMap<>();
          }

          // check if any of the current caught types are a super-class or the same as the current
          // type; if so, abort
          for (Class<?> cls : block.catchBlocks.keySet())
          {
             if (cls.isAssignableFrom(type))
             {
                return;
             }
          }

          block.catchBlocks.put(type, (Consumer) catchBlock);
       }

       /**
        * Generates a CSV file with the recorded execution statistics.
        */
       private static void dumpExecutionStats()
       {
          if (statsFile != null)
          {
             PrintWriter out = null;

             try
             {
                out = new PrintWriter(new File(statsFile));
             }

             catch (FileNotFoundException fnfe)
             {
                // TODO: log this?
             }

             if (out != null)
             {
                out.println("\"Entry Point\",\"Execution Counter\",\"Execution total time\"");

                Set<String>      keyset = stats.keySet();
                Iterator<String> keys   = keyset.iterator();

                while (keys.hasNext())
                {
                   String  entry = keys.next();
                   AtomicInteger count = stats.get(entry);
                   AtomicLong time = times.get(entry);
                   out.printf("\"%s\",\"%d\",\"%s\"\n", entry, count.get(), time.get());
                }

                out.flush();
                out.close();
             }
          }
       }

       /**
        * Helper to expose state in a way that avoids context local lookups.
        */
       static class BlockManagerHelper
       {
          /** The {@link WorkArea} instance. */
          private WorkArea wa;

          /**
           * Create a new instance and associate the given WorkArea instance.
           *
           * @param    wa
           *           The {@link WorkArea} instance.
           */
          public BlockManagerHelper(WorkArea wa)
          {
             this.wa = wa;
          }

          /**
           * Mark the start of a pending dynamic call, via {@link ControlFlowOps}.
           */
          public void markPendingDynCall()
          {
             wa.pendingDynCall = true;
          }
       }

       /**
        * Stores global data relating to the state of the current context's
        * blocks.
        */
       private static class WorkArea
       {
          /** Helper to use the TM without any context local lookups. */
          public TransactionManager.TransactionHelper tm = TransactionManager.getTransactionHelper();

          /** Helper to use the ProcedureManager without any context local lookups. */
          public ProcedureManager.ProcedureHelper pm = ProcedureManager.getProcedureHelper();

          /** Helper to use the ControlFlowOps without any context local lookups. */
          public ControlFlowOps.ControlFlowOpsHelper cfops = ControlFlowOps.getHelper();

          /** Helper to use the ObjectOps without any context local lookups. */
          public ObjectOps.ObjectHelper objHelper = ObjectOps.getObjectHelper();

          /** Helper to use the ErrorManager without any context local lookups. */
          public ErrorManager.ErrorHelper errHelper = ErrorManager.getErrorHelper();

          /** A return value for each function block on the call stack. */
          public Deque<Object> funcRet = new ArrayDeque<>();

          /** Return processing type for the current function block on the call stack. */
          public ReturnType rtype = null;

          /** Tracks the type of each top-level block as a stack. */
          public ArrayDeque<BlockType> topType = new ArrayDeque<BlockType>();

          /** Common, long-lived instance to make leave processing faster. */
          public LeaveUnwindException leaveExc = new LeaveUnwindException();

          /** Common, long-lived instance to make next processing faster. */
          public NextUnwindException nextExc = new NextUnwindException();

          /** Common, long-lived instance to make return processing faster. */
          public ReturnUnwindException retExc = new ReturnUnwindException();

          /** Object responsible for managing stop-after on Progress blocks. */
          public StopAfterTimer stopAfterTimer = null;

          /** Block name which should be left. */
          public String deferredLeave = null;

          /** Block name which should be iterated. */
          public String deferredNext = null;

          /** Flag indicating if a proc/function is executed via ControlFlowOps.invoke APIs. */
          public boolean pendingDynCall = false;

          /** Flag indicating if stop-after is enabled in directory */
          public boolean isStopAfterActive = true;

          /** A code to execute instead of the next top-level block, as the argument assignment failed. */
          public Runnable ignoreNextCall = null;

          /** Parameter indicating whether Stop condition should be raised as OO error. */
          public int catchStopParameter = SessionUtils._startupParameters().getCatchStop() != null ?
                                          SessionUtils._startupParameters().getCatchStop() :
                                          0;
       }

       /**
        * Simple container that stores and returns a context-local instance of
        * the global work area.
        */
       private static class ContextContainer
       extends ContextLocal<WorkArea>
       {
          /**
           * Obtains the context-local instance of the contained global work
           * area.
           *
           * @return   The work area associated with this context.
           */
          public WorkArea obtain()
          {
             return this.get();
          }

          /**
           * Initializes the work area, the first time it is requested within a
           * new context.
           *
           * @return   The newly instantiated work area.
           */
          protected synchronized WorkArea initialValue()
          {
             boolean stopAfter = Utils.getDirectoryNodeBoolean(null,
                                                               "legacy-system/stop-after",
                                                               true,
                                                               Utils.DirScope.BOTH,
                                                               null);
             WorkArea wa = new WorkArea();

             if (!stopAfter)
             {
                wa.isStopAfterActive = false;
             }

             return wa;
          }
       }

       /**
        * Server-wide hook that gets called at initialization and termination. We
        * use this to write out execution statistics when the statistics counters
        * are enabled.
        */
       private static class StatsHelper
       implements InitTermListener
       {
          /**
           * This method is invoked when server is about to be started.
           */
          public void initialize()
          {
             // do nothing
          }

          /**
           * This method is invoked when the server is terminating.
           *
           * @param    t
           *           Error or exception which caused exit of the server. Can
           *           be <code>null</code> if there was a normal end.
           */
          public void terminate(Throwable t)
          {
             dumpExecutionStats();
          }
       }
    }