Error Handling in CSPICE |
Table of ContentsError Handling in CSPICE Abstract CSPICE naming conventions Introduction Using CSPICE Error Handling The First Thing You Should Know What CSPICE Does About Errors, Automatically Changing What CSPICE Does About Errors Choosing Where the Error Messages Are Sent Choosing Which Error Messages to Write Example 1 Example 2 Example 3 Example 4 Example 5 Choosing the Error Response Action Handling CSPICE Errors in Your Own Program Testing the Error Status Retrieving Error Messages Getting the short message Getting the long message Getting the explanation for the short message Getting the traceback Resetting the Error Status Handling Errors Detected in Your Own Program Signaling Errors Setting the Long Error Message Using the RETURN Action and the CSPICE Function, return_c Maintaining Traceback Information -- Checking In and Checking Out Clean Coding Using failed_c Example 1 Example 2 Finding Out What the Current Error Handling Settings Are Concepts and Definitions About Errors About Error Messages The short error message The explanation of the short error message The long error message The traceback The default message About Error Response Actions Advanced Programming with Error Handling Using the CSPICE Functions failed_c and return_c Using the CSPICE routines chkin_c and chkout_c Using Multiple Settings of the Automatic Error Handling Features Error Handling in CSPICE
Abstract
CSPICE naming conventions
Introduction
About the organization of this Required Reading document: The second chapter describes ``Using CSPICE Error Handling.'' We begin with brief descriptions of the error handling features, and many examples of their use. The third chapter describes ``Definitions and Concepts.'' This chapter provides a more detailed and complete discussion of the concepts used in describing the CSPICE error handling mechanism, but generally does not give examples. Here we define what we mean by ``errors,'' describe error messages and their use, and describe the possible error processing ``actions'' -- ways of responding to error conditions. The fourth chapter describes ``Advanced Programming With Error Handling''; that chapter discusses extension of the error reporting scheme to your own application code. The document covers the following topics:
Using CSPICE Error Handling
The material in this chapter covers three areas:
The First Thing You Should Know
This capability is built into CSPICE software; you get it automatically when you link your program with CSPICE. No additional action of any kind is needed to make it work. If this behavior is adequate for your application, you don't need to read the rest of this document. What CSPICE Does About Errors, Automatically
See the section ``About Error Messages'' below for details. Changing What CSPICE Does About Errors
Choosing Where the Error Messages Are Sent
For example, to have error messages go to the file, ERROR.DAT, you could use the following code:
/* Set the error output device for CSPICE to the file ERROR.DAT: */ errdev_c ( "SET", lenout, "ERROR.DAT" );This call should precede calls to other CSPICE routines, except erract_c and errprt_c. If your program has an initialization portion, this call should go there. Choosing Which Error Messages to Write
Change the set of written messages via a call to the CSPICE routine, errprt_c. The first argument should be 'SET'. The second argument is a list of message types that you want to ADD to the set of messages that currently are selected to be output when an error occurs. The keywords which may be used in the list:
SHORT LONG EXPLAIN TRACEBACK DEFAULT ALL ( write all messages ) NONE ( write no messages )The list of message choices is read from left to right, with each word ADDING to the previous set of messages (except for the word NONE, which subtracts all of the messages from your selection). Some examples may help clarify this. Example 1
/* Add the long message to the set selected for output when an error occurs: */ errprt_c ( "SET", lenout, "LONG" );Now the short and long messages will be output if CSPICE detects an error. Example 2
/* Just output the long message when an error occurs: */ errprt_c ( "SET", lenout, "NONE, LONG" ); Example 3
/* Just output the long message and traceback on error: */ errprt_c ( "SET", lenout, "NONE, TRACEBACK, LONG" ); Example 4
/* Don't output ANY CSPICE error messages on error: */ errprt_c ( "SET", lenout, "NONE" ); Example 5
/* Output ALL CSPICE error messages on error: */ errprt_c ( "SET", lenout, "ALL" );See the section ``About Error Messages'' below for details. Choosing the Error Response Action
CSPICE's error handling mechanism allows you to choose one of several different error response ``actions.'' In almost all cases, the only reasonable alternative to the default action is RETURN. Briefly, the full set of choices consists of:
You use erract_c to set the error response action. The first argument should be 'SET'. The second argument should be one of the above choices. For example:
/* Set the SPICELIB error response action to "RETURN": */ erract_c ( "SET", lenout, "RETURN" ); Handling CSPICE Errors in Your Own Program
The automatic error reporting feature is meant to produce human- readable error diagnostic information. However, you may also wish to have your program respond to CSPICE errors. To do this, you will need to know about three more basic functions: testing and resetting the CSPICE error status, and retrieving CSPICE error messages. Testing the Error Status
For example, suppose you call the CSPICE routine, rdtext_c, to read a line of text from a file. You want your program to test whether an error occurred on the read. You can write:
/* Read a line from userfile.txt; check for errors: */ rdtext_c ( "userfile.txt", line_len, line, &eof ); if ( failed_c() ) { return; }If you're used to routines that have error arguments, you might note that the code is similar to what you would write if FAILED were an output argument for rdtext_c, instead of a function. However, there are a number of advantages to the CSPICE method, one of which is that if you don't wish to write any error handling code to handle CSPICE errors, you don't have to, and you'll still get helpful error messages automatically. Also, if you use CSPICE error handling in your own code, you don't need error arguments, which makes for simpler code. Retrieving Error Messages
This feature is useful for two reasons. First, if you want your program to take different actions depending on what error occurred, it gives your program a way to find out. Second, if you want to generate your own error reports instead of using those generated by CSPICE, you need to be able to retrieve the information CSPICE has generated about the error. Getting the short message
To retrieve the short error message, call getmsg_c or getsms_. For example:
/* Call prompt_c to prompt the user for the name of file to read from. Read a line from it. Check for errors: */ prompt_c ( "Enter file name > ", file_len, file ); rdtext_c ( file1, line_len, line, &eof ); while ( !eqstr_c ( file, "" ) ) { if ( failed_c () ) { /* An error occurred. Find out what the short message was: */ getmsg_c ( "SHORT", shrtms_len, shrtms ); if ( eqstr_c( shrtms, "SPICE(NOFREELOGICALUNIT)" ) || eqstr_c( shrtms, "SPICE(TOOMANYFILESOPEN)" ) ) { /* We won't succeed in reading any file. So, quit. */ return; } else { /* Get name of a different file: */ prompt_c ( "Enter file name > ", file_len, file ); } } } Getting the long message
To get the long error message, call getmsg_c or getlms_. For example,
rdtext_c ( file, line_len, line, &eof ); if ( failed_c() ) { /* Get long message and output it. */ getmsg_c ( "LONG", longms_len, longms); printf ( "%s \n", longms ); }The argument supplied to getmsg_c should be declared char *. Getting the explanation for the short message
Here's an example:
/* After this call, EXPL will take the value: "Invalid Radius--Equatorial or Polar Radius is Zero" */ expln_( "SPICE(ZERORADIUS)", expln, 17L, expln_len); printf ( "%s \n", expln ) Getting the traceback
/* Get traceback. After the call to qcktrc_, TRACE should have the value, "MAIN --> SUBA --> SUBB" */ qcktrc_(trace, trace_len); printf ( "%s \n", trace );
trcdep_ ( depth ); for ( i=0; i< depth; i++ ) { trcnam_( i , name , name_len); printf ( "%s \n", name ); } Resetting the Error Status
An example would be the case where you have an interactive program that prompts the user for the name of a file to read. Your program uses the CSPICE function rdtext_c to read the file. If the file isn't found, rdtext_c signals an error. The inability to locate the file need not stop the program; your program could just display a message saying the file wasn't found and ask for another file name. The problem here is that the CSPICE functions failed_c and return_c will return the `true' value after rdtext_c signals the error, so any code whose logic depends on the value of those functions will behave as if an error has occurred, even though the error was recoverable. To solve this problem, CSPICE provides the routine, reset_c, which ``resets'' the error handling mechanism, so that it acts as if no error had occurred. Calling reset_c has the following effects:
Handling Errors Detected in Your Own Program
Some of the capabilities that you get with CSPICE are:
Signaling Errors
When sigerr_c is called, all of the types of error messages that have been selected for automatic output are written out, and CSPICE takes whatever additional actions are required by the current setting of the error response ``action.'' sigerr_c takes one input argument, a short (25 character maximum) error message. This message will be output if the ``short message'' has been selected for output. It is strongly recommended that your code supply a descriptive (at least non-blank) error message when it calls sigerr_c. The short message, if used, indicates the type of error which occurred, so the program can respond appropriately. A capability exists to set a long, human-readable, error message. The next section discusses setting the long message. Here's an example in which the routine, DACOSH, signals an error.
/* DACOSH computes an arc hyperbolic cosine of X; X must be greater than or equal to 1 to be in the domain of DACOSH. Check that x >= 1. */ if ( x < 1. ) { setmsg_c ( "DACOSH: Invalid argument, X is less than one." ); sigerr_c ( "SPICE(INVALIDARGUMENT)" ); return; }You may note a call to the routine setmsg_c precedes the call to sigerr_c as setmsg_c sets the long error message. setmsg_c is discussed in the next section, but we'll note here that if you wish to call setmsg_c, it should be called BEFORE calling sigerr_c, since sigerr_c causes the current long error message to be output. Setting the Long Error Message
You may supply a character string of length up to 1840 characters as the input argument to setmsg_c. Strictly speaking, the long message is optional, but it's recommended that you call setmsg_c before every call to sigerr_c, supplying a blank string if you don't wish to set a long message. As an example, the calls to setmsg_c and sigerr_c from the example in the last section are repeated here:
setmsg_c ( "DACOSH: Invalid argument, X is less than one." ); sigerr_c ( "SPICE(INVALIDARGUMENT)" );Frequently, one would like to insert variable strings into a long message. In the above example, it might be nice to convert X, a double precision number, to a character string and put it in the error message. CSPICE provides the routine, errdp_c, for just this purpose. errdp_c takes two arguments. The first is a character string to appear in the long error message. It marks the place where the result of the conversion is to be placed in the long error message. The second argument is the value to be converted to a character string. The resulting string is substituted for the first occurrence of the first argument found in the long message. Here's the previous example, re-written using ERRDP.
/* Set long error message, with a MARKER where the value of X will go. Our marker is '#'. */ setmsg_c ( "DACOSH: Invalid argument, x<1. The value is #."); /* Convert X to characters, and insert the result in the long message where the # is now: */ errdp_c ( "#", x ); /* If x happened to be -5.5D0, for example, the long message becomes: "DACOSH: Invalid argument, x < 1. The value is -5.5D0." Signal the error: */ sigerr_c ( "SPICE(INVALIDARGUMENT)" );In addition to errdp_c, errint_c and errch_c are provided for inserting integers and character strings into the long message. Using the RETURN Action and the CSPICE Function, return_c
CSPICE solves this problem with the boolean function return_c, and the RETURN error response action. The first two lines of executable code of every CSPICE routine that can detect errors, or that calls another routine, are:
if ( return_c () ) { return; }When the error action is RETURN and an error has been signaled, return_c takes the `true' value. So every CSPICE routine that can detect errors, or that calls another routine, returns without doing anything. This greatly reduces the chance of an error causing a program crash. You can use the function return_c in your own code to achieve the same effect. return_c always takes the `false' value if the error action is not RETURN. See the next section to find out what the rest of the IF block should be. Maintaining Traceback Information -- Checking In and Checking Out
As an example, suppose the following figure shows the calling hierarchy for a program, and that currently, subroutine ``E'' is executing, after being called by ``C.''
MAIN / | \ B C D / \ /| | E F E HThe active call chain would consist of ``MAIN,'' ``C,'' and ``E.'' The traceback message, if retrieved at this point, would be:
MAIN --> C --> ETo make your own code participate in the traceback scheme, every routine in your program (except those that call nothing else and don't detect errors) should ``check in'' on entry and ``check out'' on exit. These actions tell the error handling mechanism whether your routine is in the active call chain or not. To check in, call chkin_c, supplying the name of your routine. To check out, call chkout_c, also supplying the name of your routine. The call to chkin_c should come immediately after each entry into your code. A call to chkout_c should precede each exit made after checking in. For example:
/* Here's a skeleton of code for a mock routine, suba: Executable code follows */ if ( return_c() ) { /* No check out here, since we haven't checked in. */ return; } else { chkin_c ( "suba" ); } . . . if ( x < 1. ) { /* First exit following check in: */ chkout_c ( "suba" ); return; } . . . /* Normal exit: */ chkout_c ( "suba" ); return;The traceback storage can accommodate a stack depth of 100 routines; the maximum length of each stored name is 32 characters. Clean Coding Using failed_c
Example 1
/* Read a line from userfile1.txt, userfile2.txt, and userfile3.txt; check for errors: */ rdtext_c ( "userfile1.txt", line1_len, line1, &eof ); rdtext_c ( "userfile2.txt", line1_len, line2, &eof ); rdtext_c ( "userfile3.txt", line1_len, line3, &eof ); if ( failed() ) { /* Not all of line1, line2, line3 are valid, so quit: */ chkout_c ( "mysub" ); return; } Example 2
/* In the following code, copyc is used to copy the result of the union of two sets (ordered cells) from a temporary working set back into one of the original sets. */ union_c( &bod, &planets, &temp ); copy_c ( &temp, &bod ); if ( failed_c() ) { chkout_c ( "mysub" ); return; } /* If the size of the temporary cell is greater than the size of the original set, failed_c() should be checked to be sure that no overflow occurred. If bodies is at least as large as temp, no such check is necessary. */You can also use this coding technique with calls to your own routines, if your use the function return_c. Finding Out What the Current Error Handling Settings Are
For example, you find out which device error output is sent to:
errdev_c ( "GET", lenout, device ); /* device, with length lenout, now contains the name of the output device. */To find out what the current error response action is:
erract_c ( "GET", lenout, action ); /* action, with length lenout, now contains the current error response action. */To find out what the current error message selection is:
errprt_c ( "GET", lenout, list ); /* list now contains the last list of messages that was input by a call to errprt_c. If no call was made, list has the value "DEFAULT". */ Concepts and DefinitionsAbout Errors
When an error is detected because a routine has been used improperly, information about the context of the error is desirable. It's useful to know in which routine the error was detected, what the call chain was at the time of the error, and what the inputs to the routine that detected the error were. The CSPICE error handling mechanism is designed to provide this type of information. On the other hand, when it's the program's job to determine the correctness of data, information about the program is not what is wanted when an error occurs. In this case, information about the data is what's needed. CSPICE's automatic error handling is not appropriate for dealing with this type of error. However, it is possible to shut off the automatic error handling, using the IGNORE error action, and use non-CSPICE code to handle these errors. In general, CSPICE's automatic error handling is most useful for diagnosing programming errors. The only errors that the CSPICE error handling mechanism deals with are DETECTABLE ones. CSPICE can test whether a calling routine has supplied an argument that's in the domain of a function, but it can't tell if the calling routine has the order of the arguments in a calling sequence reversed. By coincidence, an error may be detected in that case, but the diagnosis will point to the error in an indirect way, at best. And if an application uses a faulty algorithm, but nonetheless uses the CSPICE routines correctly, SPICELIB can't tell you about it. Some detectable errors exist which CSPICE does not detect. While attempted division-by-zero errors are prevented, floating overflow is generally not prevented (because doing so is too inefficient). When a CSPICE routine detects an error, it may mean the routine is being used improperly. One of the most likely causes is an interface error: inputs may be supplied to the routine that it can't handle, or there may be an error in the coding of the call to the routine itself. It's a good idea to thoroughly understand the descriptions of inputs and outputs given in the module headers of each CSPICE routine called by one's application. Some other possible causes of errors may be: bugs in application software, bugs in CSPICE software, or bad inputs to the application program. Errors can also occur due to problems with the program's environment. For example, an attempt to open a file could fail because the application program didn't have the privileges necessary to perform the open, or on some systems, because the file was in use by another user. About Error Messages
CSPICE provides routines for setting and retrieving error messages. When a routine detects an error, it may ``set,'' or store, error messages, which then can be retrieved and examined by other routines. There are five types of error messages:
The short error message
SPICE(...)where the message text goes between the parentheses. An example is:
SPICE(FILEOPENFAILED)The text is always composed of upper case letters and numbers. Short error messages used in CSPICE are CONSTANT, since they are intended to be used in code. That is, they don't contain any data which varies with the specific instance of the error they indicate. Because of the brief format of the short error messages, it is practical to use them in a test to determine which type of error has occurred. For example:
rdtext_c ( file, line_len, line, &eof ); if ( failed()_c ) { /* An error occurred. Find out what the short message was: */ getmsg_c ( "SHORT, shrtms_len, shrtms ); if ( eqstr_c(shrtms, "SPICE(NOFREELOGICALUNIT)" ) || eqstr_c(shrtms, "SPICE(TOOMANYFILESOPEN)" ) ) { /* We won't succeed in reading any file. So, quit. */ return; } } else { . . .If you use the CSPICE error mechanism to respond to errors detected in your own code, you may wish to use your own short error messages. The CSPICE error handling mechanism doesn't make use of the actual content of the messages, so you may use any values that are practical. It may be of use to make up your own prefix (analogous to CSPICE's ``SPICE'' ), to identify the errors as detected by your own code. Recall the 25-character limit; excess characters will be truncated. We recommend that you do NOT use blank short error messages. While the error handling mechanism allows it, the short error messages would no longer be useful for enabling code to determine the type of error that has occurred. The short message is ``set'' by supplying it as an input argument to the CSPICE routine sigerr_c. It is retrieved by calling getmsg_c or getsms_. The explanation of the short error message
CSPICE provides the routine expln_ to map short error messages to their explanations. Currently, there is no provision to extend the mapping to user-defined short messages. In future versions of CSPICE, more space may be allocated for explanations. However, expln_ will continue to return the first 80-character line of the explanation text in that case. Here's an example of a short message and the corresponding explanation:
Short message: "SPICE(ZERORADIUS)" Explanation: "Invalid Radius--Equatorial or Polar Radius is Zero" The long error message
Long error messages generated by CSPICE routines often contain data relevant to the specific error they describe. Here's an example of a long error message generated by a misspelled body name provided as an input to the CSPICE function spkezr_c:
The observer, 'earthh', is not a recognized name for an ephemeris object. The cause of this problem may be that you need an updated version of the SPICE toolkit. Alternatively you may call SPKEZ directly if you know the SPICE ID codes for both 'moon' and 'earthh'The long message is ``set'' by supplying it as an input argument to the CSPICE routine setmsg_c. It may be retrieved by calling getmsg_c or getlms_. The routines, errdp_c, errint_c, and errch_c provide the capability to insert data into the long message. Their respective purposes are to insert double, int, and char * data into the long message. They (except errch_c) convert the input data to a character string, and insert it in the current long message at a location indicated by a user-specified marker. We strongly recommend that you DO NOT write code that tests for particular values of CSPICE long error messages; this is a very error-prone practice. The traceback
You can have your own code participate in the CSPICE traceback scheme, so that the traceback will represent the entire active call chain. Knowledge of the active call chain can be a valuable debugging aid, because it helps you determine where in your program an error occurred. For example, if your program calls subroutine SUBX from ten different subroutines, it's not enough to know that SUBX detected an error; you want to know which subroutine made the offending call to SUBX. The traceback contains that information. Another example: suppose a CSPICE routine in your program detects an error, but your own code does not call that routine. You need to know which call, made by your own code to a CSPICE routine, eventually resulted in the call to the routine that detected the error. The traceback shows you this. The CSPICE error handling mechanism automatically keeps track of which CSPICE routines are in the active call chain. In order for the CSPICE error handling mechanism to represent the entire active call chain, including non-CSPICE routines, it is necessary for each routine to tell the error handling mechanism: 1) when it has been called and 2) when it is about to return. In CSPICE documentation, these two operations are called ``checking in'' and ``checking out.'' The set of routines that have checked in but have not yet checked out constitute the portion of the active call chain that the CSPICE error handling mechanism can represent. CSPICE provides the two routines chkin_c and chkout_c for this purpose; chkin_c for checking in, and chkout_c for checking out. chkin_c and chkout_c take one input argument: the name of the calling routine. The traceback message has the form of a list of subroutine names, delimited by arrows. The first name in the list is the highest-level routine in the portion of the active call chain that is known to the CSPICE error handling mechanism. As an example, suppose the following figure shows the calling hierarchy for a program, and that currently, subroutine ``E'' is executing, after being called by ``C.''
MAIN / | \ B C D / \ /| | E F E HThe active call chain would consist of ``MAIN,'' ``C,'' and ``E.'' The traceback message, if retrieved at this point, would be:
MAIN --> C --> EThe particular traceback information made available by CSPICE is dependent on the error action and on whether an error has occurred. In general, the routines qcktrc_, trcdep_, and trcnam_ return information about the current active call chain. But when the error response action is RETURN, and an error occurs, the error handling mechanism captures a ``frozen'' copy of the traceback; from this point on, the trace information provided by the above routines will be based on the frozen copy. The purpose of this behavior is to make the traceback that existed at the time the error occurred available to the application program. Changing the error action to a value other than RETURN, or resetting the error status, will cause the traceback routines qcktrc_, trcdep_, and trcnam_ to return data based on the current traceback again. The overhead of checking in and checking out may be prohibitive for some routines. An intermediate position between not using chkin_c and chkout_c and using them in every routine is to use them only in routines that call other routines, or that detect errors. Routines which do neither would never appear in a traceback anyway. Note that absence of error detection in a routine is not sufficient grounds for exclusion from checking in and checking out, since a routine called by the routine in question could detect an error, and then the caller should appear in the traceback. It is important to note that ONLY routines which have checked in can possibly have their names appear in the traceback. So the traceback will not be accurate if any routines in the active call chain have not ``checked in,'' when a traceback message is produced. The traceback mechanism requires any ``checked-in'' routine to check out before exit. The default message
About Error Response Actions
There are five different error response actions, each appropriate to a different type of programming situation:
Returning control to the non CSPICE portion of the program allows for a response to the error condition. The nature of the response is application-dependent. However, in the case that the error does not preclude further successful operation of the program, it is necessary to instruct the CSPICE error handling mechanism that normal operation is desired, after the error has been responded to. The CSPICE function RESET is provided for this purpose. Calling RESET blanks out all stored error messages, and causes the functions FAILED and return_c to take the `false' value.
Note that the IGNORE action is not appropriate for the case where you wish to suppress automatic output of CSPICE error messages, and to handle CSPICE errors in your own code. To do that, use the RETURN error action and set the selection of error messages to 'NONE', using errprt_c. Advanced Programming with Error Handling
Using the CSPICE Functions failed_c and return_c
Which routines should use the function return_c, and where? The ``which?'' question is somewhat tricky: there's a trade-off between speed and resistance to program crashes. It takes time (not much) to test return_c, and in a very short routine, such as one that computes a dot product, the execution time can be increased by a substantial factor if return_c is tested. In most routines, the percentage increase in execution time is small. So, if you don't want to test return_c in every routine, how do you decide? The CSPICE answer to this question is, test return_c in routines that call other routines or detect errors (CSPICE routines that are specifically intended to perform error handling are exempt from testing return_c). If a routine calls another routine already, it's unlikely that testing return_c will slow its execution intolerably. Similarly for routines that test for error conditions. Our final answer is still a hedge: the proper use of return_c depends on your speed and reliability requirements. The CSPICE method may be a good zero-order approximation to what's optimal. NOTE: You must be very careful about using return_c in application code that DOES error handling, otherwise your error handling code itself may not function when an error is signaled. The ``where?'' question also eludes a straightforward answer. The idea behind the RETURN action is to ensure that control is returned to whatever part of your program handles errors, when an error is signaled. According to this idea, once an error has been signaled, you have to do something about the error before you can finish the job. So, routines that do use return_c ought to test it at the very beginning of their executable code; there's no reason for them to proceed further until the error condition has been acted upon. What about using the function return_c in other parts of the code, for instance following calls to CSPICE routines? The same speed vs crash resistance trade-off applies, but there is another consideration: return_c has an effect only when the error action is RETURN. So, in cases where an error condition makes it likely that a portion of code won't work, it's usually better to test the function failed_c, rather than return_c, since a program crash is usually undesirable, even when using the REPORT action for debugging. But if you do want to retain the option of executing the code when an error has already occurred, use return_c. We repeat here that the CSPICE function failed_c indicates whether an error has been signaled, regardless of the error response action. It can be used to avoid executing any code that may cause a run-time error if an error has already occurred. Note that testing failed_c instead of return_c means that whether the error response action is RETURN or REPORT doesn't affect the program logic in question; the logic depends on whether or not an error has been signaled. Using the CSPICE routines chkin_c and chkout_c
The CSPICE approach is to call chkin_c and chkout_c in routines which call other routines or which can detect errors. This way, every routine that can possibly be in the active call chain at the time an error is detected can appear in the traceback message. As mentioned in the previous section, these routines are less likely to suffer a large percentage increase in execution time as a result of making extra calls. We note that some routines that do make external references but do not signal errors may have no routines capable of signaling errors below them in the calling hierarchy; these routines won't appear in a traceback. Why should they call chkin_c and chkout_c? They should do so for maintenance reasons, specifically, if any routine below them in the calling hierarchy is changed so as to be able to detect an error, the higher level routines don't need to be changed. Using Multiple Settings of the Automatic Error Handling Features
/* All errors in the following section of code are fatal. Temporarily set the error action to "ABORT"; restore old action after end of code section. */ erract_c ( "GET", len_savact, savact ); erract_c ( "SET", len_savact, "ABORT" ); { Section of code in which errors are fatal starts here } . . . { Section of code in which errors are fatal ends here } /* Restore old error action: */ erract_c ( "SET", len_savact, savact );Changes to the error output device or error message selection can be made in the same way; both errdev_c and errprt_c accept the values ``GET'' and ``SET'' for their first argument.
|