Chapter 6
Errors and Exceptions

 6.1 ICL Exceptions
 6.2 Exception Handlers
 6.3 Keyboard Aborts
 6.4 SIGNAL command

6.1 ICL Exceptions

Error conditions and other unexpected events are referred to as Exceptions in ICL. When such a condition is detected in direct mode a message is output. For example, if we enter a statement which results in an error

      ICL> =SQRT(-1)
      SQUROONEG   Square Root of Negative Number
      ICL>

We get a message consisting of the name of the exception (SQUROONEG) and a description of the nature of the exception. A full list of ICL exceptions is given in appendix C.

If the error occurs within a procedure the message contains a little more information. As an example, if we use our square root procedure of Section 3.11 with an invalid value we get the following messages:

      ICL> SQUARE_ROOT (-1)
      SQUROONEG   Square Root of Negative Number
      In Procedure: SQUARE_ROOT
      At Statement: PRINT  The Square Root of (X) is (SQRT(X))
      ICL>

If one procedure is called by another, the second procedure will also be listed in the error message. If we run the following procedure

      PROC TABLE
      {  Print a table of Square roots from 5 down to -5  }
         LOOP FOR I = 5 TO -5 STEP -1
           SQUARE_ROOT (I)
         END LOOP
      END PROC

we get

      ICL> TABLE
      The Square Root of 5 is 2.236068
      The Square Root of 4 is 2
      The Square Root of 3 is 1.732051
      The Square Root of 2 is 1.414214
      The Square Root of 1 is 1
      The Square Root of 0 is 0
      SQUROONEG   Square Root of Negative Number
      In Procedure: SQUARE_ROOT
      At Statement: PRINT  The Square Root of (X) is (SQRT(X))
      Called by: TABLE
      ICL>

6.2 Exception Handlers

It is often useful to be able to modify the default behaviour on an error condition. We may not want to output an error message and return to the ICL > prompt, but rather to handle the condition in some other way. This can be done by writing an exception handler. Here is an example of an exception handler in the SQUARE_ROOT procedure.

      PROC SQUARE_ROOT X
      {  An ICL procedure to print the square root of a number   }
        PRINT The Square Root of (X) is (SQRT(X))
  
        EXCEPTION SQUROONEG
          {  Handle the imaginary case  }
          SQ = SQRT(ABS(X))
          PRINT The Square Root of (X) is (SQ&’i’)
        END EXCEPTION
  
      END PROC

Now running the TABLE procedure gives

      ICL> TABLE
      The Square Root of 5 is 2.236068
      The Square Root of 4 is 2
      The Square Root of 3 is 1.732051
      The Square Root of 2 is 1.414214
      The Square Root of 1 is 1
      The Square Root of 0 is 0
      The Square Root of -1 is 1i
      The Square Root of -2 is 1.414214i
      The Square Root of -3 is 1.732051i
      The Square Root of -4 is 2i
      The Square Root of -5 is 2.236068i
      ICL>

The Exception handler has two effects. First the code contained in the exception handler is executed when the exception occurs. Second, the procedure exits normally to its caller (in this case TABLE) rather than aborting execution completely and returning to the ICL > prompt.

Exception handlers are included in a procedure following the normal code of the procedure but before the END PROC statement. There may be any number of exception handlers in a procedure, each for a different exception. The exception handler begins with an EXCEPTION statement specifying the exception name, and finishes with an END EXCEPTION statement. Between these may be any ICL statements, including calls to other procedures.

An exception handler does not have to be in the same procedure in which the exception occurred, but could be in a procedure further up in the chain of calls. In our example we could put an exception handler for SQUROONEG in TABLE rather than in SQUARE_ROOT.

      PROC TABLE
      {  Print a table of Square roots from 5 down to -5  }
         LOOP FOR I = 5 TO -5 STEP -1
           SQUARE_ROOT (I)
         END LOOP
  
         EXCEPTION SQUROONEG
            PRINT ’Can’’t handle negative numbers - TABLE Aborting’
         END EXCEPTION
      END PROC

giving:

      ICL> TABLE
      The Square Root of 5 is 2.236068
      The Square Root of 4 is 2
      The Square Root of 3 is 1.732051
      The Square Root of 2 is 1.414214
      The Square Root of 1 is 1
      The Square Root of 0 is 0
      Can’t handle negative numbers - TABLE aborting
      ICL>

Below is an example of a pair of procedures which use an exception handler for floating point overflow in order to locate the largest floating point number allowed on the system. Starting with a value of 1 this is multiplied by 10 repeatedly until floating point overflow occurs. The highest value found in this way is then multiplied by 1.1 repeatedly until overflow occurs. Then by 1.01 etc.

      PROC LARGE  START, FAC, L
  
      { Return in L the largest floating point number before        }
      { overflow occurs when START is repeatedly multiplied by FAC  }
  
        L = START
        LOOP
          L = L * FAC
        END LOOP
  
        EXCEPTION FLTOVF
        { This exception handler doesn’t have any code - it just  }
        { causes the procedure to exit normally on overflow       }
        END EXCEPTION
      END PROC
  
      PROC LARGEST
  
      {  A Procedure to find the largest allowed floating point   }
      {  number on the system                                     }
  
        FAC = 10.0
        LARGE  1.0,(FAC),(L)
        LOOP WHILE FAC > 0.00000001
           LARGE (L),(1.0+FAC),(L)
           FAC = FAC/10.0
        END LOOP
  
        PRINT  The largest floating point number allowed is (L)
      END PROC

6.3 Keyboard Aborts

One exception which is commonly encountered is that which results when a Control-C is entered on the terminal. This results in the exception CTRLC and may therefore be used to abort execution of a procedure and return ICL to direct mode. However, an exception handler for CTRLC may be added to a procedure to modify the behaviour when a control-C is typed.

6.4 SIGNAL command

The exceptions described up to now have all been generated internally by the ICL system, or in the case of CTRLC are initiated by the user. It is also possible for ICL procedures to generate exceptions, which may be used to indicate error conditions. This is done by using the SIGNAL command. This has the form

      SIGNAL  name  text

where name is the name of the exception, and text is the message text associated with the exception. The exception name may be any valid ICL identifier. Exceptions generated by SIGNAL work in exactly the same way as the standard exceptions listed in appendix C. An exception handler will be executed if one exists, otherwise an error message will be output and ICL will return to direct mode.

One use of the SIGNAL command is as a means of escaping from deeply nested loops. The BREAK statement can be used to exit from a single loop but is not applicable if two or more loops are nested. In these cases the following structure could be used

      LOOP
        LOOP
          LOOP
            .
            IF FINISHED
              SIGNAL ESCAPE
            END IF
            .
          END LOOP
        END LOOP
      END LOOP
  
      EXCEPTION ESCAPE
      END EXCEPTION

where the exception handler again contains no statements, but simply exists to cause normal procedure exit, rather than an error message when the exception is signalled.