|
|
|
|
||
|
DEFINITION MODULE Errors; (******************************************************************* Module Errors (Version 1.0) Copyright (c) 1995-2006 by Andreas Fischlin and ETH Zurich. Purpose Provides simple and consistent error handling for errors detected by algorithms from library modules. Remarks The module provides convenient mechanisms to generate error messages and to control their display. In particular, it enables a programmer to suppress any error display by an algorithm residing in a lower level library module, yet all local information describing the error can be fully retrieved for display or explanation to the user by the calling program. The module is basically an enhancement of DMMessages (see the "Dialog Machine" kernel modules). Typical Usage (a code excerpt): ... FROM Errors IMPORT allOk, ActivateMessageFile, SetInsert, AppendInsert, Str, IStr, RStr, Info, Halt, Kill; ... VAR inserts: ARRAY [0..255] OF CHAR; resCode, aninteger: INTEGER; ... (* The following routine returns the message text msg associated with the message or error number msgnr. Note, the symbol Δ (=306C) denotes a so-called place-holder which will be replaced by the actual parameter passed for inserts while calling Info, Halt, or Kill (see below), usually rendering message texts much more understandable if they contain specific information, e.g. the name of an actual operand etc.: *) PROCEDURE MyGetMsg (msgnr: INTEGER; VAR msg: ARRAY OF CHAR); BEGIN CASE msgnr OF | 1: AssignString("Please select first a Δ",msg); | 2: AssignString("Can't find model object 'Δ'",msg); AppendLnBreak(msg); Append(msg,"(Hint: Check existence of model)"); | 3: AssignString("... ... ELSE msg[0] := 0C; (* signals to Errors to look for other sources *) END(*CASE*); END MyGetMsg; (* The following routine provides an alternative mechanism (see above MyGetMsg) for associating message texts with error numbers. In this case you need to pass GetMessage or GetNumberedMessage from MsgFile as actual paramter for getMsg while calling any of the routines Info, Halt, or Kill (see below). *) ActivateMessageFile("Errors.DOC",TRUE, resCode); ... (* Declare the resCode range for range-specific handling of error messages, e.g. 20 resCodes: *) minRC = userBase + 700; maxRc = minRC + 20; SetErrHdlgModes(suppressed,debug,minRC,maxRC,installed); (* now an example of generating a warning in an algorithm of the library module: *) ... SetInsert(inserts,Str("a string insert item")); AppendInsert(inserts,IStr(aninteger),); Halt(errCode,MyGetMsg,"MyModule","ProcedureName",inserts); (* or *) Halt(errCode,MsgFile.GetMessage,"MyModule","ProcedureName",inserts); (* if ActivateMessageFile has previously been called *) ... (* Upon returning from the algorithm in the library module, a final handling of the error by the callee: *) ... GetErrHdlgModes(suppressed,debug,minRC,maxRC, installed); IF suppressed THEN FOR i := -1 TO OldestErrIndex(minRC,maxRC) BY -1 DO GetError(i,err); WITH err DO ... (* e.g. analyze it and construct a custom message myErr *) END(*WITH*); END(*FOR*); (* e.g. display custom message: *) DisplayAnError(myErr); ... (* or display one found in the list, e.g. only the last: *) DoInfo(err.resCode,MsgFile.GetMessage, "MyModule","ProcedureName",err.inserts); (* or use just the field msg: *) DoInfo(onlyAnInsert,MsgFile.GetMessage, "MyModule","ProcedureName",err.msg); ... (* finally don't forget to discard the stored errors, they are no longer needed: *) ForgetErrHistory(minRC,maxRC); END(*IF*); (* or do it just the poor man's way: *) ... DisplayErrHistory(minRC,maxRC); (* But note, above poor man's way may display a large, confusing number of messages in a row, without allowing for proper debugging, since the procedure chain does no longer match that which was present at error detection. Finally note, by activating the forced debugging mode, e.g. by pressing Command^Shift^Capslock^D simultaneously, can you force an immediate display of messages at all times. It offers the advantage of proper debugging, even it the programmer has suppressed the error display. *) Programming o Design Andreas Fischlin 08/09/1995 o Implementation Andreas Fischlin 08/09/1995 ETH Zurich Systems Ecology CHN E 35.1 Universitaetstrasse 16 8092 Zurich SWITZERLAND URLs: <mailto:RAMSES@env.ethz.ch> <http://www.sysecol.ethz.ch> <http://www.sysecol.ethz.ch/SimSoftware/RAMSES> Last revision of definition: 31/03/1998 AF *******************************************************************) FROM DMStrings IMPORT String; FROM DMMessages IMPORT MsgRetrieveProc; (*********************************) (*##### Error Constants #####*) (*********************************) (* Note, the following error constants are compatible with the ones used by the "Dialog Machine", especially the codes supported by module 'DMLanguage' and are all by default available from 'DMLanguage'. *) CONST allOk = 0; (* General 'Dialog Machine' *) badProgState (* should not occurr *) = -4; onlyAnInsert = -3; unknownErr = -2; insuffMem = -1; tooOldMac = 9; tooManyTermProc = 10; (* DMWindIO arithmetic *) intOverflow = 1; lowUpSame = 2; (* User Input (DMEntryForms etc.) *) numExpected = 5; outOfRange = 7; wrongChar = 3; wrongCharOrNone = 14; only1Char = 4; only1CharOrNone = 15; stringTooLong = 16; (* Object access *) unknownWindow = 8; unknownEditField = 6; unknownGraph = 11; (* DM2DGraphs *) noLogScale = 12; graphTooSmall = 17; (* DMFiles: Subsequent message order fits DMFiles.Response, i.e. code = fileResBase+ORD(f.res) *) fileResBase = 20; fileNotFound = 21; volNotFound = 22; fileDlgCancelled = 23; unknownFile = 24; tooManyFiles = 25; diskFull = 26; insuffMemForFileFct = 27; fileAlreadyOpen = 28; fileIsBusy = 29; fileIsLocked = 30; fileFctNotDone = 31; (* reserved for Dialog Machine Auxiliary Library is range 100..199 *) notImplemented = 100; userInterrupted = 101; (* reserved for Dialog Machine applications is range 200..300. In use as of April 1998: 201, 202, 299 *) (* Error constants beyond userBase may be used freely and do not conflict with any constants used by the 'Dialog Machine' *) userBase = 300; (******************************************) (*##### Error Message Generation #####*) (******************************************) PROCEDURE Info (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); PROCEDURE Halt (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); PROCEDURE Kill (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); (* Above routines are similar to the ones exported by DMMessages, but they know about current display and debug mode settings and behave accordingly. For explanations of default behavior see DMMessages (for Info see DoInform; for Halt see DoWarn; for Kill see DoAbort). Typical usage: VAR inserts: ARRAY [0..63] OF CHAR; ... SetInsert(inserts,Str(f.filename)); AppendInsert(inserts,IStr(maxNum)); Info(resCode,MyGetMsg,"MyModule","Reading",inserts); ... Note, the routine getMsg has to provide a message text associated with the msgnr. Typically it is a routine written by the programmer, but can also be on of these: DMLanguage.GetString, DMStrings.GetRString, DMMsgFile.GetMessage, or DMMsgFile.GetNumberedMessage. This technique enables to have several clients using this module at the same time since getMsg is used only temporarily to generate the error message; the previous settings are restored upon returning from any of these routines. *) PROCEDURE DoInfo (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); PROCEDURE DoHalt (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); PROCEDURE DoKill (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); (* Provided for your convenience, above routines are similar to Info, Halt, and Kill. They know about current display and debug mode settings and behave accordingly, except for the flag suppress which they ignore, i.e. they always produce the error message immediately regardless of the current settings. For instance DoInfo corresponds exactly to the following code: PROCEDURE DoInfo (msgnr: INTEGER; getMsg: MsgRetrieveProc; modIdent, locDescr, insertions: ARRAY OF CHAR); VAR saveSuppress: BOOLEAN; BEGIN (*DoInfo*) GetErrHdlgModes(saveSuppress,... SetErrHdlgModes(FALSE,... Info(msgnr, getMsg, modIdent, locDescr, insertions); SetErrHdlgModes(saveSuppress,... END DoInfo; Typically these routines are used by the callee of auxiliary library routines after having suppressed any immediate message display to finally inform the user about the error(s) which occurred. They are a full replacement of the corresponding DMMessages routines, since they behave similarily but offer the advantages of switching the message retrieve procedure automatically according to the current settings and that they know about the current debug mode settings. *) VAR nil: String; PROCEDURE DbgMsg (modIdent, locDescr: ARRAY OF CHAR; s1,s2,s3,s4,s5: String); (* Displays a message concatenated from all string parameters s1..s5 only if debugging mode is currently activated (see section on modes); otherwise any message generation is suppressed. For the meaning of modIdent and locDescr see routines DMMessages.DoInform, DoWarn respectively DoAbort. The message is always produced on the warn level only (see DMMessages.DoWarn), which allows for an optional calling of the debugger and messages are never deferred but always displayed at generation time. *) PROCEDURE ReplacePlaceHolders (VAR newMsg: ARRAY OF CHAR; oldMsg, insertions: ARRAY OF CHAR); (* Copies oldMsg into newMsg by replacing the place holders in oldMsg (Mac 'Δ' (=306C), IBM-PC '^') with the string items found in variable insertions. E.g. ReplacePlaceHolders(newMsg, "Δ is out of range [Δ..Δ]","-1|2|3"); ==> newMsg = "-1 is out of range [2..3]" *) PROCEDURE AppendLnBreak (VAR s: ARRAY OF CHAR); (* Causes in the string s to appear a line break. Typically used while programming your own GetMessage routine (see sample code MyGetMsg above). *) (****************************************) (*##### Insertion Construction #####*) (****************************************) PROCEDURE SetInsert(VAR inserts: ARRAY OF CHAR; s: String); (* First item to be put into inserts used for place holders in messages *) PROCEDURE AppendInsert (VAR inserts: ARRAY OF CHAR; s: String); (* Append another item to inserts used for place holders in messages *) PROCEDURE Str(s: ARRAY OF CHAR): String; (* Convert string s to String for passing to AppendInsert. E.g. SetInsert(Str("First insert item"),inserts); *) PROCEDURE IStr (x: INTEGER): String; PROCEDURE LIStr (x: LONGINT): String; (* Convert integer number x to String for passing to AppendInsert. E.g. AppendInsert(IStr(231),inserts); *) PROCEDURE RStr (x: REAL): String; PROCEDURE LRStr (x: LONGREAL): String; (* Convert real number x to String for passing to AppendInsert. E.g. AppendInsert(RStr(2.345),inserts); *) PROCEDURE BStr (x: BOOLEAN): String; (* Convert boolean x to String for passing to AppendInsert. E.g. AppendInsert(BStr(flag),inserts); *) (************************************) (*##### Setting Up & Modes #####*) (************************************) (************************************************************************ The following optional routines allow to activate and customize any subsequent error message handling, i.e. to tell this module e.g. where to get error message texts and how to display them. This module assumes the following: - each error detected and to be handled by your code belongs to a certain error class, where the lowest level simply informs the user, the second warns her (makes it possible to call the debugger), or aborts the program (debugger can also first be called). For more details see underlying module DMMessages. - each error is encoded by a unique integer (errNo, msgNr, or resCode) and associated with a specific message text which can be displayed to the user. Such texts may not be fully predefined, but can be completed by variable information only available at run-time. The latter is called insertions which are to replace placeholders (on the Macintosh = 'Δ'(=306C), on the IBM-PC = '^') in the predefined message text. First a technique needs to be available to the message generating routines of this module which enable them to retrieve the message text associated with a given error code. There are two basic techniques available to accomplish this: - Program your own MyGetMsg procedure to return a specific message text associated with a given error number (for sample code see below). This technique is the most flexible and robust method. - ActivateMessageFile is used to retrieve messages from a text file which is easy to maintain let's you keep the code of applications smaller, and which provides a good overview if many error messages are to be managed. Important NOTE: Error messages for error codes already defined by the 'Dialog Machine' (i.e. codes < userBase) are automatically retrieved from the DM, unless they are defined again. Not only does this enable to override any definition as defined by the DM but also to inherit any error messages which are already defined by DMLanguage. If you use a message file, i.e. you call ActivateMessageFile, at a time you can use only a single message file, due the implementation restriction by the underlying module MsgFile. If you wish to use more than one message file you have to switch the message file before each message generation (likely to be inefficient). For the display of errors or messages, this module can basically operate in three modes: 1) suppress TRUE, i.e. any immediate error or message generation is suppressed. Instead the information is stored and accumulated in memory; debug FALSE 2) immediate (= NOT suppress), i.e. any error or message generation takes place immediately, i.e. the very moment of their generation; nothing is stored in memory, debug FALSE 3) debug TRUE implies NOT suppress, i.e. any error or message generation takes not only place immediately - a prerequisite for meaningful debugging -, but can also produce additional, debugging messages which remain otherwise always hidden and turns Info messages into Halt ones (see above). The latter allows the user to call the debugger each time a message generating routine from this module is called. The flag 'suppress' controls whether the display of messages by Info, Halt, or Kill (see below) is immediate (right at generation moment) or whether these routines display nothing and contribute only towards accumulating a so-called error history. The error history is stored for deferred display or analysis by the callee or display to the end user. The possibility to suppress immediate display of error messages, allows for writing code, typically in a library module, which can call Info, Halt etc. as soon as an error is detected by the algorithm, regardless of the current message display mode. Yet, depending on the suppress mode, the actual display of these messages to the end user may be deferred, e.g. the callee want's to inform the user later in a more context specific way than this would be possible by a general purpose library module. With this technique, the implementation of error generation within general purpose library modules can be elegantly separated from client error handling including the display to the end user. The implementor can program the former freely and in a logical, algorithm suitable way; and the callee can program the latter in whichever way she likes (see routines GetError, DisplayAnError below). If suppress = TRUE, any number of errors generated by the routines Info, Halt, or Kill are stored in memory for later retrieval. Entire error history can be inspected anytime for a sophisticated error analysis and/or display. By default suppress = FALSE. It is also possible to activate a global debugging mode in which additional debugging messages become visible and in which it is possible to call the debugger during any message generation. This is typically used during testing phases (available also in final, end-user software), where the deferring of message display can be suppressed and step by step software execution is desired. This mode can be activated by means of not so obvious keyboard shortcuts anytime during program execution. Finally, this module provides means to subdivide errors and their associated messages according to their unique resCode numbers into three classes: - range-specific errors/messages - non range-specific (so-called global) errors/messages - all errors/messages (unification of the two above) The first type is characterized by a specific range of resCodes ([minResCode..maxResCode]) as given by a lower (minResCode) and upper limit (maxResCode). The second type encompasses all other resCodes, which fall not into one of the ranges known to this module. They form the class of the so-called global or non-range specific error messages. Finally, the third type include any possible resCode; some routines operate on all errors and error messages, regardless wether its resCode's are range-specific or not, i.e. global ones. The class global errors is useful for displaying also errors which are likely to be encountered in the middle of an operation, which "normally" uses a specific range for its own specific errors. E.g. errors occurring during file operations typically belong to the global error class, since a matrix package reading matrices from a file may use range-specific errors for its specific error reporting, e.g. a badly defined matrix, yet errors caused by a file operation should still be displayable. Global errors are those shared by several software packages using their own specific error ranges, i.e. global errors form a common class of errors. It is important to note that every range can have its own suppress and debugging modes. Range specific modes affect only errors or messages falling within range [minResCode .. maxResCode]. Ranges and their modes can be installed via routine SetErrHdlgModes (see below). Range-specific modes allow for the coexistence of several software packages, each using its particular mode of operation when using this module Errors. Ranges may not overlap and must be unique globally at run time. Any handling of global error messages is preinstalled by this module, with suppress = FALSE, debug = FALSE (see routine SetErrHdlgModes). The three types are specified by using particular range intervals [minResCode .. maxResCode ] range-specific [globResCode .. globResCode] non range-specific (global) [allResCode .. allResCode ] unification of the two above where minResCode <> MIN(INTEGER) maxResCode <> MAX(INTEGER) globResCode = MIN(INTEGER) allResCode = MAX(INTEGER) ************************************************************************) (*-----------------------------------------*) (*===== Setting Up A Message File =====*) (*-----------------------------------------*) PROCEDURE ActivateMessageFile(errDocFN: ARRAY OF CHAR; VAR resCode: INTEGER); (* Initialize error message display mechanism if you hold the error messages in a file named "errDocFN". There is only one message file which can be used at a time. Thus using a message file is typically reserved for global errors only, i.e. errors or messages with a resCode which falls NOT within one of the installed ranges. If resCode is not allOk, e.g. if the error document file could not be found, suppress is forced TRUE, to avoid unpredictable results during subsequent error handling. It is highly recommended to call at least DisplayErrHistory immediately after this routine, if it is called with suppress = TRUE. *) (*------------------------------------*) (*===== Error Handling Modes =====*) (*------------------------------------*) CONST globResCode = MIN(INTEGER); allResCode = MAX(INTEGER); PROCEDURE SetErrHdlgModes(suppress,debug: BOOLEAN; minResCode,maxResCode: INTEGER; VAR done: BOOLEAN); (* Set mode for error message display to 'suppress', 'debug' for the generation or display respectively of any messages with a resCode falling in range [minResCode..maxResCode]. 'suppress' = TRUE => any subsequent immediate message display will be suppressed, but messages are stored in memory in form of an error history for later retrieval. 'debug' = TRUE => In debugging mode error messages as generated by routine DbgMsg (see above) become visible and all messages as generated by routines Info, Halt, or Kill (see above) are always immediately displayed regardless of the current display mode (see routine SuppressMsgDisplay). The latter makes it possible to properly debug the program behavior, since only at error detection is the procedure chain the one you're interested in. Moreover, in this mode, errors of class inform can be debugged since they are treated as messages at the warn level. [minResCode..maxResCode] denotes the range and thereby the interval of resCode's for which the passed modes ('suppress' and 'debug') are effective (range-specific modes). To be effective for non range-specific resCode's, pass range [globResCode..globResCode]. To affect all at once regardless of range-specificity pass range [allResCode..allResCode]. Parameter 'done' returns about successful installation of range-specific modes. It may fail due to memory limitations (see below) or range errors. Note, SetErrHdlgModes does not allow for overlapping ranges, e.g. if another software layer has installed error modes for a range which overlaps with range [minResCode..maxResCode], this will lead to a failure of SetErrHdlgModes. However, you may call SetErrHdlgModes as many times you wish, as long as the range as given by the actual parameters minResCode and maxResCode matches exactly one previously installed. Then Errors assumes that the same callee is using the range and that SetErrHdlgModes simply wishes to alter the current mode settings. IMPORTANT NOTE: Keyboard shortcut "Command^Shift^Capslock^D" (or alternatively "Command^Shift^Capslock^G") toggles the forced debug mode on or off. It's effect is similar to calling SetErrHdlgModes(FALSE, TRUE, allResCode, allResCode, done), however, "Command^Shift^Capslock^D" overrules the settings for particular ranges only temporarily. After having toggled the forced debug mode off, previous modes will be restored; this is not the case after a call to SetErrHdlgModes passing range [allResCode..allResCode]. IMPLEMENTATION RESTRICTION: Only a limited number of error ranges can be supported. *) PROCEDURE GetErrHdlgModes(VAR suppress,debug: BOOLEAN; minResCode,maxResCode: INTEGER; VAR installed: BOOLEAN); (* Returns the current modes effective for errors falling within range [minResCode..maxResCode]. 'installed' returns wether SetErrHdlgModes has ever been called for the given range. Calling this routine with globResCode as actual argument for range limits, will return the so-called global modes 'suppress' and 'debug'. They are effective for all messages with a resCode not falling within one of the ranges declared by means of SetErrHdlgModes. *) PROCEDURE ForgetRange (minResCode,maxResCode: INTEGER; VAR done: BOOLEAN); (* Tells the module to forget about the range [minResCode..maxResCode]. 'done' returns upon success of action, e.g. may fail if range has never be installed of it has been automatically remove, e.g. the calling subprogram level is no longer present. *) (****************************************) (*##### Handling Error History #####*) (****************************************) (*------------------------------------------*) (*===== Easy Retrieval and Display =====*) (*------------------------------------------*) PROCEDURE NoOfMsgs (minResCode,maxResCode: INTEGER): INTEGER; (* Returns the number of error messages presently stored in memory with a resCode which falls within range [minResCode..maxResCode]. *) PROCEDURE AskAndViewErrHistory(minResCode,maxResCode: INTEGER; withGlobMsg : BOOLEAN; VAR answeredToView : BOOLEAN; doViewOnUserYes : BOOLEAN); (* High level utility to handle at once all currently present error messages which fall into range [minResCode..maxResCode] and/or global error messages (withGlobMsg = TRUE) as follows: If a single error message is present it is displayed immediately (returns answeredToView = FALSE). If more than one is found, the user is informed about the number of messages present and asked if she wishes to view them ('answeredToView' returns what the user answered, i.e. whether she has wished to view the messages or not). If doViewOnUserYes = TRUE then the routine calls ViewErrHistory automatically in case the user has answered to view the messages (answeredToView = TRUE), otherwise no further displays are made and the callee may call her own message display algorithm. A typical call to this routine looks like this: AskAndViewErrHistory (myMinRC,myMaxRC,TRUE,answView,TRUE); *) PROCEDURE ViewErrHistory(minResCode,maxResCode: INTEGER; withGlobMsg: BOOLEAN); (* Displays the error history currently stored in memory for all messages which fall into range [minResCode..maxResCode] and/or global error messages (withGlobMsg = TRUE) in chronological order (indices from OldestErrIndex(..) .. -1). Note, does nothing if there are currently no errors stored. To prevent repeated displays of the same error message(s), ViewErrHistory calls at the end implicitely also ForgetErrHistory for the involved ranges. For alternatives to this routine see also routine DisplayErrHistory (reverse order) or AskAndViewErrHistory. Note, the viewing of error messages can anytime be aborted by pressing key 'q' (quit) or 'c' (cancel). *) PROCEDURE DisplayErrHistory(minResCode,maxResCode: INTEGER); (* Displays the error history currently stored in memory for all messages which fall into range [minResCode..maxResCode] in reverse order of occurrence, i.e. starting with the most recent one (-1), then the previous one (-2) etc. (indices from -1 .. OldestErrIndex(..)). Note, does nothing if there are currently no errors stored. To prevent repeated displays of the same error message(s), DisplayErrHistory calls at the end implicitely also ForgetErrHistory for range [minResCode..maxResCode]. For alternatives to this routine see also routine ViewErrHistory (chronological order) or AskAndViewErrHistory. Note, the viewing of error messages can anytime be aborted by pressing key 'q' (quit) or 'c' (cancel). *) (*----------------------------------------------------*) (*===== Full Analysis, Retrieval and Display =====*) (*----------------------------------------------------*) CONST noMoreErrs = 0; TYPE ErrorClass = (inform, warn, fatal); (* for explanation see DMMessages *) ErrorDescr = RECORD class: ErrorClass; msg: ARRAY [0..255] OF CHAR; (* holds entire message text *) (* the following fields hold only information which was used to construct msg and may be optionally of use *) resCode: INTEGER; modIdent, locDescr, insertions: ARRAY [0..255] OF CHAR; END(*RECORD*); PROCEDURE OldestErrNo(): INTEGER; (* Returns the index of the oldest error of the currently stored history of all errors, global and range specific ones, e.g. -2. Returns 0 if there are no errors stored. *) PROCEDURE GetError(n: INTEGER; VAR err: ErrorDescr); (* Retrieves the error description of the n'th error. Such error descriptions are generated and stored by calls to any of the procedures Info, Halt, or Kill while flag suppress is TRUE. n designates the error occurrence in reverse order, where -1 is the very last error, -2 the error which occurred before the last one, -3 the even earlier one etc. Typically used immediately after returning from a routine, which has been called while suppress was TRUE. It allows for analyzing the error and for displaying a custom error message or for taking whatever action the callee prefers (see also DisplayErrHistory). Only errors stored since the last call to procedure ForgetErrHistory or DisplayErrHistory can be retrieved. If n designates an error exceeding those currently actually stored, an empty err is returned with err.class = inform, err.resCode = allOk, and all string fields = "". GetError does not change the storage of the internal error history. *) PROCEDURE DisplayAnError(VAR err: ErrorDescr); (* Immediately displays the error as described by err according to its class and the other fields. *) PROCEDURE OldestErrIndex(minResCode,maxResCode: INTEGER): INTEGER; (* Returns the index of the oldest error of the currently stored history for error messages with a resCode which falls within range [minResCode..maxResCode]. Returns 0 if there are no errors stored. Note, the index is a number between OldestErrNo() and 0. *) PROCEDURE NextErrIndex (fromIndex,minResCode,maxResCode: INTEGER): INTEGER; PROCEDURE PrevErrIndex (fromIndex,minResCode,maxResCode: INTEGER): INTEGER; (* Similar to OldestErrIndex but return the next/previous error index of the error message which chronologically follows/preceeds message 'fromIndex' (see also DisplayErrHistory which uses only PrevErrIndex starting with 'fromIndex' = 0). Returns 0 if there are no more errors stored. Note, the index is a number between OldestErrNo() and 0, where indices may be returned not as a complete series, but with gaps inbetween, e.g. if the history contains inbetween a message falling into another range. Use the returned index as actual argument when calling GetError. Ex.: CONST noMoreErrs = 0; i := OldestErrIndex(minResCode,maxResCode); WHILE (i<>noMoreErrs) DO GetError(i,err); DisplayAnError(err); i := NextErrIndex(i,minResCode,maxResCode); END(*WHILE*); *) (*--------------------------------------*) (*===== Clearing Error History =====*) (*--------------------------------------*) PROCEDURE ForgetErrHistory(minResCode,maxResCode: INTEGER); (* Discards entire, currently stored error history for all messages with a resCode falling within range [minResCode..maxResCode]. Any subsequent calls to GetError return an empty error or to DisplayErrHistory display nothing unless at least one of the procedures Info, Halt, or Kill has been called again while flag suppress was set to TRUE (see also procedure GetError). No effect if range has never been installed. ForgetErrHistory(allResCode, allResCode) discards all error messages at once, regardless of ranges. *) (************************************) (*##### Module Maintenance #####*) (************************************) PROCEDURE ResetErrors; (* Resets the entire module to its predefined, initial defaults. All current error handling modes are set to their defaults, internal state is reset, message display is not suppressed (suppress := FALSE), no error message file will be used any more, debugging modes are all off, and any error history is discarded. *) END Errors.
|
||
|
|
|