8 MAPPING CHARACTER DATA

Although the previous example used a numeric type of ‘_REAL’ to access the data, HDS actually allows any primitive type to be specified as an access type, including ‘_CHAR’. In the particular case of mapping data as character strings, however, there are some additional considerations imposed by the way that compilers handle this data type. These are described here.

HDS gives you a choice about how to determine the length of the character strings it will map. You may either specify the length you want explicitly, e.g:

  CALL DAT_MAPV( LOC ’_CHAR*30’, ’READ’, PNTR, EL, STATUS )

(in which case HDS would map an array of character strings with each string containing 30 characters) or you may leave HDS to decide on the length required by omitting the length specification, thus:

  CALL DAT_MAPV( LOC ’_CHAR’, ’READ’, PNTR, EL, STATUS )

In this latter case, HDS will determine the number of characters actually required to format the object’s values without loss of information. It uses decimal strings for numerical values and the values ‘TRUE’ and ‘FALSE’ to represent logical values as character strings. If the object is already of character type, then its actual length will be used directly. The routine DAT_MAPC also operates in this manner.

On most UNIX systems, the length of a character string is passed to a subroutine by the compiler, which adds an additional “invisible” length argument to the end of the subroutine call for each character argument passed. Unfortunately, a compiler cannot recognise the data type of a mapped array, so it will not be able to automatically add length information about mapped character strings. This information must therefore be passed explicitly.

As an example, suppose we mapped an array of character strings specifying that each string should be of length 80 characters, thus:

  CALL DAT_MAPV( LOC, ’_CHAR*80’, ’READ’, PNTR, EL, STATUS )

This mapped array could be passed to a subroutine for use as follows:

  INCLUDE ’CNF_PAR’
  
  ...
  
  CALL SHOW( EL, %VAL( CNF_PVAL( PNTR ) ), %VAL( CNF_CVAL( 80 ) ) )

The character string length (80) is passed as an additional argument (which does not appear in the formal argument list of the SHOW subroutine) using the “%VAL” facility. The array would then be declared for use within this routine as if it were a normal Fortran character array, as follows:

  SUBROUTINE SHOW( EL, CARRAY )
  INTEGER EL
  CHARACTER * ( * ) CARRAY( EL )
  ...

Its character string length could then be determined, as usual, by using the Fortran intrinsic LEN function within the SHOW routine.

Note that if an access mode of ‘_CHAR’ were specified when mapping the array (leaving HDS to determine the length of the mapped strings) then an additional call to DAT_CLEN would be required to determine this length, as follows:

  ...
  INTEGER LENGTH
  
  CALL DAT_MAPV( LOC, ’_CHAR’, ’READ’, PNTR, EL, STATUS )
  CALL DAT_CLEN( LOC, LENGTH, STATUS )
  CALL SHOW( EL, %VAL( CNF_PVAL( PNTR ) ), %VAL( CNF_CVAL( LENGTH ) ) )

If more than one mapped character array is being passed, then the length of each must be passed separately by adding it to the end of the argument list. This must be done in the same order as the arrays themselves are passed.

Unfortunately, this technique will only work if there are no other character values being passed at earlier points in the argument list. Otherwise, there is no way of adding additional length information so that it appears in the correct position relative to the “invisible” information that the compiler will already have generated for the other argument(s). The only solution in such cases is to provide a dummy routine whose purpose is simply to permute the argument order so that mapped character arrays may be passed at the start of the formal argument list.