next up previous
Next: Scalar Values between Limits
Up: PAR Interface to the ADAM Parameter System
Previous: Null

Extended Routines  

  In addition to the basic routines there are some packaged facilities for common sequences of calls. Most deal with dynamic control of acceptable values when getting the parameter. Some are needed because the in choices and range limits imposed by the ADAM interface module are static, and therefore cannot be adjusted depending on the values of other parameters or data. Note that in the extended routines that follow, all call a PAR_GETnx routine which first checks that each supplied value satisfies these interface-file constraints, and prompts for a new value if it does not. Only after these tests are made will each value be compared with the constraints in the extended routines. Therefore, you are recommended not to use the in and range fields for parameters obtained using the extended routines.

Here is an example of handling your own constraints to illustrate why it is more convenient to use the packaged routines, where applicable, and also to demonstrate how you might write your own extended routine should you need one. It is a little contrived, since the PAR library already provides the most-common combinations.

Here we obtain from parameter NAME an integer that is not exactly divisible by 3, set the dynamic default to 1, and interpret null to mean set the value to 3. See SUN/104 for details of the MSG_ calls.

          LOGICAL NOTOK
          INTEGER VALUE

              :       :       :

    *  Set the dynamic default.
          CALL PAR_DEF0I( 'NAME', 1, STATUS )

    *  Start a new error context.
          CALL ERR_MARK

    *  Loop to obtain the value of the parameter.
    *  ==========================================

    *  Initialise NOTOK to start off the loop and indicate that a 
    *  satisfactory value has yet to be obtained.
          NOTOK = .TRUE.

      100 CONTINUE

    *  The loop will keep going as long as a suitable value has not be read
    *  and there is no error.
             IF ( .NOT. NOTOK .OR. ( STATUS .NE. SAI__OK ) ) GOTO 120

    *  Get a value from the parameter.
             CALL PAR_GET0I( 'NAME', VALUE, STATUS )

    *  Check for an error before using the value.
             IF ( STATUS .EQ. SAI__OK ) THEN

    *  Test the value against the constraints.  Here it is just to see
    *  if the value is divisible by 3.  You can replace this expression
    *  with more complicated constraints.
                NOTOK = MOD( VALUE, 3 ) .EQ. 0

    *  The value is not within the constraints, so report as an error,
    *  including full information using tokens.  You would substitute a 
    *  routine name for fac_xxxxx.
                IF ( NOTOK ) THEN
                   STATUS = SAI__ERROR
                   CALL MSG_SETC( 'PARAM, 'NAME' )
                   CALL MSG_SETI( 'VALUE', VALUE )

                   CALL ERR_REP( 'fac_xxxxx_OUTR',
         :           '^VALUE is not permitted for ^PARAM.  Please give '/
         :           /'an integer not exactly divisible by 3.', STATUS )

    *  The error is flushed so the user can see it immediately.
                   CALL ERR_FLUSH( STATUS )

    *  Cancel the parameter to enable a retry to get a value satisfying
    *  the constraint.
                   CALL PAR_CANCL( 'NAME', STATUS )
                END IF

    *  Use the default value following an error.
             ELSE

    *  Annul a null error to prevent an error report about null appearing.
    *  Create a message informing the user of what has happened.
                IF ( STATUS .EQ. PAR__NULL ) THEN
                   CALL ERR_ANNUL( STATUS )

    *  If MSG verbose output is requested, inform the user what has happened.
    *  You would substitute a routine name for fac_xxxxx.
                   CALL MSG_SETC( 'PARAM', 'NAME' )
                   CALL MSG_OUTIF( MSG__VERB, 'fac_xxxxx_DEFA',
         :           'A value of 3 has been adopted '/
         :           /'for parameter ^PARAM.', STATUS )
                END IF

    *  Set the returned value to the special case.
                VALUE = 3

    *  Terminate the loop.
                NOTOK = .FALSE.
             END IF

    *  Go to the head of the loop.
             GOTO 100

    *  Come here when the loop has been exited.  This includes when
    *  an error status was returned by the PAR_GET0I routine.
      120 CONTINUE

    *  Release the new error context.
          CALL ERR_RLSE

To set another constraint you have to modify the logical expression for variable NOTOK, and revise the ERR_REP error report, possibly with more tokens. Suppose variables VMIN and VMAX define a range of permitted values, which is inclusive when VMAX is the larger of the two and exclusive when VMAX is less than VMIN. The constraint expression could modified to the following.

    *  Check that the value is within the specified include or exclude
    *  range, and not divisible by 3.
            IF ( VMIN .GT. VMAX ) THEN
               NOTOK = ( ( VALUE .LT. VMIN ) .AND. ( VALUE .GT. VMAX ) )
     :                 .OR. ( MOD( VALUE, 3 ) .EQ. 0 )
            ELSE
               NOTOK = ( VALUE .LT. VMIN ) .OR. ( VALUE .GT. VMAX ) .OR.
     :                 ( MOD( VALUE, 3 ) .NE. 0 )
            END IF

and the error report would look something like this

    *  The value is not within the constraints, so report as an error,
    *  including full information using tokens. 
                IF ( NOTOK ) THEN
                   STATUS = PAR__ERROR
                   CALL MSG_SETC( 'PARAM', 'NAME' )
                   CALL MSG_SETI( 'VALUE', VALUE )
                   CALL MSG_SETI( 'MIN', VMIN )
                   CALL MSG_SETI( 'MAX', VMAX )
                   IF ( VMIN .GT. VMAX ) THEN
                      CALL MSG_SETC( 'XCLD', 'outside' )
                   ELSE
                      CALL MSG_SETC( 'XCLD', 'in' )
                   END IF

                   CALL ERR_REP( 'fac_xxxxx_OUTR',
     :               '^VALUE is not permitted for ^PARAM.  Please give '/
     :               /'an integer ^XCLD the range ^MIN to ^MAX, and not '/
     :               /'exactly divisible by 3.', STATUS )

In practice you would probably define a logical variable outside the loop to indicate whether the range was inclusive or exclusive.[*]

Having looked `behind the scenes', we can now look at what the PAR_ extended routines offer.



 

next up previous
Next: Scalar Values between Limits
Up: PAR Interface to the ADAM Parameter System
Previous: Null

PAR Interface to the ADAM Parameter System
Starlink User Note 114
Malcolm J. Currie
Alan J. Chipperfield
1999 September 24
E-mail:ussc@star.rl.ac.uk