Next: Examples of Possible User Responses
Up: An Example of a Simple GRP Application
Previous: An Example of a Simple GRP Application
Here is a simple example of the use of GRP which illustrates the ideas of
indirection and modification. In this example, each stored string corresponds to
the name of a file but obviously an application could apply other
interpretations. The user is prompted for a set of input file names and then
prompted again for a set of output file names. Each input file is processed in
some way (by routine PROC) to produce the corresponding output file. The source
code that follows is not intended to provide all the information necessary to
write GRP applications, but simply to give a feeling for the way GRP works:
SUBROUTINE GRP_TEST( STATUS ) [1]
IMPLICIT NONE
* Include definitions of global constants.
INCLUDE 'SAE_PAR' [2]
INCLUDE 'GRP_PAR' [3]
* Declare local variables.
INTEGER STATUS, IGRP1, IGRP2, SIZE1, SIZE2, ADDED, I
CHARACTER*(GRP__SZNAM) INFIL, OUTFIL
LOGICAL FLAG
* Check inherited global status.
IF ( STATUS .NE. SAI__OK ) RETURN [4]
* Create a new (empty) group to contain the names of the
* input files.
CALL GRP_NEW( 'Input files', IGRP1, STATUS ) [5]
* Prompt the user for a group of input file names and place
* them in the group just created.
CALL GRP_GROUP( 'IN_FILES', GRP__NOID, IGRP1, SIZE1, [6]
: ADDED, FLAG, STATUS )
* Create a second group to hold output file names.
CALL GRP_NEW( 'Output files', IGRP2, STATUS ) [7]
* Prompt the user for a group of output file names, giving
* the chance to specify them by modification of the input
* file names. Place the output file names in the new group
* just created.
CALL GRP_GROUP( 'OUT_FILES', IGRP1, IGRP2, SIZE2, [8]
: ADDED, FLAG, STATUS )
* Report an error and abort if the number of output files
* does not equal the number of input files.
IF( SIZE2 .NE. SIZE1 .AND. STATUS .EQ. SAI__OK ) THEN [9]
STATUS = SAI__ERROR
CALL ERR_REP( 'GRP_TEST_ERR1',
: 'Incorrect number of output files specified',
: STATUS )
GO TO 999
END IF
* Loop round each input file.
DO I = 1, SIZE1 [10]
* Retrieve the input file name with index given by I.
CALL GRP_GET( IGRP1, I, 1, INFIL, STATUS ) [11]
* Retrieve the output file name with index given by I.
CALL GRP_GET( IGRP2, I, 1, OUTFIL, STATUS )
* Process the data.
CALL PROC( INFIL, OUTFIL, STATUS ) [12]
* Do the next input file.
END DO
* Delete the groups created by this application.
999 CONTINUE
CALL GRP_DELET( IGRP1, STATUS ) [13]
CALL GRP_DELET( IGRP2, STATUS )
END
Programming notes:
- The example is actually an ADAM A-task, and so consists of a subroutine with
a single argument giving the inherited status value. See
SUN/101 for further
details about writing ADAM A-tasks. A ``stand-alone'' version of the GRP package
is available which can be used with non-ADAM applications.
- The first INCLUDE statement is used to define standard ``symbolic
constants'', such as the values SAI__OK and SAI__ERROR which are used in
this routine. Starlink software makes widespread use of such constants, which should always
be defined in this way rather than by using actual numerical values. The file
SAE_PAR is almost always needed, and should be included as standard in every
application.
- The second INCLUDE statement performs a similar function to the first, but
defines symbolic constants which are specific to the GRP package. Such constants
are recognizable by the fact that they start with the five characters
``GRP__'' (such as GRP__NOID and GRP__SZNAM used in the above example).
Note the double underscore ``__'' which distinguishes them from subroutine
names.
- The value of the STATUS argument is checked. This is because the
application uses the Starlink error handling strategy (see
SUN/104), which
requires that a subroutine should do nothing unless its STATUS argument is set
to the value SAI__OK on entry. Here, we simply return without action if STATUS
has the wrong value.
- An identifier for a new group is now obtained. The variable IGRP1 is
returned holding an integer value which the GRP package uses to recognise the
group just created. Initially, there are no names stored in the group. A string
is stored which should be used to give a description of the type of objects
stored within the group (in this case the string ``Input files'' is
used).
- The user is now prompted for a value for the parameter IN_FILES, and
replies with a string, which GRP splits up into separate elements, each element
being either a literal file name or the name of a text file containing other
file names. As there are no other groups defined at this point, it is not
possible to specify the files names using ``modification'' (as described in item
in section
). For this reason, the second argument
(which would normally specify the group to use as the basis for modification) is
given the value GRP__NOID. This is a special identifier value used to indicate
a ``null'' group. The names supplied by the user are stored in the group created
by the previous call to GRP_NEW, and the number of names is returned in
argument SIZE1.
Note, no permanent association exists between the group
identified by IGRP1 and the parameter IN_FILES (which is one reason why
GRP_GROUP is not called GRP_ASSOC). The parameter value may be cancelled (for
instance using PAR_CANCL) without effecting the contents of the
group.
- A second group is now created to hold the output file names. The two
groups are distinguished by the fact that they have different identifiers
(stored in IGRP1 and IGRP2).
- The user is prompted again, this time for a value for
the parameter OUT_FILES and the names obtained are stored in the second group
just created. Again the user can give literal files names and/or the names of
text files holding other file names. Now that there are two groups, it is
possible to use modification to specify the output files. The identifier for the
group containing the input files names is given as the second argument of
GRP_GROUP, telling the GRP system that if the user specifies output file
names using modification (which may not be the case of course), then the output
file names are to be derived by modifying the input file names stored in the
first group.
- In this particular application it is deemed necessary to
have equal numbers of input and output files, but GRP imposes no restrictions on the
number of strings which can be supplied when responding to a prompt from
GRP_GROUP. It is therefore necessary to check the that the two groups contain
the same number of elements. A more sophisticated application might seek user
intervention to determine how to proceed at this point (either by requesting
extra output file names or by ignoring some). Note, if some other error has already been detected (as shown by
STATUS having a value other than SAI__OK), then the check on the number of
input and output files is irrelevant.
- Having stored the input file names in one group and the output file names
in another, the application now loops through each pair of input and output file
names in turn. An ``index'' I is used to distinguish between different
elements within a group. The input file name with index I is retrieved from the
first group and the output file name with the same index is retrieved from the
second group.
- Note, there is a limit to the size of the character string which can be
stored in a GRP group. This size is given by the symbolic constant GRP__SZNAM.
- A routine is now called which uses the two file names; a typical routine
may take data out of the input file, process it and store the results in the
output file. The file handling itself would be done within the routine PROC.
This example actually makes no assumptions about what the strings stored in the
two groups represent (the descriptive strings stored when the two groups were
created are of no significance in this application). Although, for clarity, it
has been assumed that the strings correspond to file names, they could just as
easily have been wavelengths, the names of astronomical objects, calender dates,
or just about anything else.
- Finally, the groups created by this application are deleted. This is
particularly important in applications which run as subroutines within a wider
context (such as ADAM applications). There is a limited number of groups
available, and if applications forget to delete the groups they have created,
then the possibility of exceeding the limit then exists. Note, the groups should
be deleted even if the application aborts because of an error, so the statement
labelled 999 (to which a jump is made if an error is detected) comes before the calls to GRP_DELET.
Next: Examples of Possible User Responses
Up: An Example of a Simple GRP Application
Previous: An Example of a Simple GRP Application
GRP Routines for Managing Groups of Objects
Starlink User Note 150
D.S. Berry
21st October 2009
E-mail:ussc@star.rl.ac.uk
Copyright © 2009 Science and Technology Facilities Council