A Examples

 A.1 Create a file with name that is specific to a user
 A.2 Get some virtual memory

So much for theory, here are some examples of the use of PSX routines. Each POSIX routine tends to stand on its own, so the examples are fairly simple.

A.1 Create a file with name that is specific to a user

The requirement is to create a file that will be used to hold the output of several programs, but this file must be in a directory that is used by several people. Clearly the file name must be related to the username. Also it is necessary to take into account the difference in the syntax of directory names on VMS and Unix systems.

        PROGRAM NEWFIL
  
        IMPLICIT NONE
        INCLUDE ’SAE_PAR’
        INTEGER STATUS                   ! The global status value
        CHARACTER * ( 32 ) NAME          ! The name of the current user
        CHARACTER * ( 80 ) FILNAM        ! The name of the file to be created
        CHARACTER * ( 15 ) SYSNAME       ! The name of the operating system
        CHARACTER * ( 1 ) DUMMY1
        CHARACTER * ( 1 ) DUMMY2
        CHARACTER * ( 1 ) DUMMY3
        CHARACTER * ( 1 ) DUMMY4
  
  * Set STATUS since this is is not an ADAM program.
        STATUS = SAI__OK
  
  * Get the username.
        CALL PSX_GETENV( ’USER’, NAME, STATUS )
  
  * Get the system name.
        CALL PSX_UNAME( SYSNAME, DUMMY1, DUMMY2, DUMMY3, DUMMY4, STATUS )
  
  * Create the file.
        IF( STATUS .EQ. SAI__OK ) THEN
           IF( SYSNAME .EQ. ’VMS’ ) THEN
              FILNAM = ’COMMON_AREA:’ // NAME // ’.DAT’
           ELSE
              FILNAM = ’/usr/common/’ // NAME // ’.DAT’
           END IF
           OPEN( UNIT=1, FILE=FILNAM, STATUS=’NEW’ )
           CLOSE( UNIT=1 )
        ELSE
           PRINT *,’Could not get username’
        END IF
  
        END

Although the PSX routines are designed to be used with other Starlink routines in the ADAM environment and use the concept of inherited status, they can just as easily be used in a stand alone program like the one above provided that the status is set correctly before calling the first routine. This is important since the PSX routine will exit immediately if STATUS is not set to the value of the symbolic constant SAI__OK.

A.2 Get some virtual memory

One of the annoying features of FORTRAN 77 is that all storage space must be allocated at compile time, i.e. there are no dynamic arrays. Here is an example of using PSX routines to dynamically allocate an array.

        PROGRAM MAIN
        IMPLICIT NONE
        INCLUDE ’SAE_PAR’
        INTEGER STATUS
  
  * Set the STATUS to OK.
        STATUS = SAI__OK
  
  * Call the subroutine.
        CALL GETVM( STATUS )
  
        END
  
  
        SUBROUTINE GETVM( STATUS )
        IMPLICIT NONE
        INCLUDE ’SAE_PAR’
        INCLUDE ’CNF_PAR’
        INTEGER STATUS, PNTR
  
  * Check global status.
        IF( STATUS .NE. SAI__OK ) RETURN
  
  * Create a ten element integer array and return a pointer to it.
        CALL PSX_CALLOC( 10, ’_INTEGER’, PNTR, STATUS )
  
  * If all is well, operate on the array.
        IF (STATUS .EQ. SAI__OK) THEN
           CALL FILL( %VAL(PNTR), 10 )
           CALL PRNT( %VAL(PNTR), 10 )
           CALL PSX_FREE( PNTR, STATUS )
        END IF
  
        END
  
  
        SUBROUTINE FILL( ARRAY, N )
  * Put some numbers in the array.
        INTEGER N, ARRAY( N )
        INTEGER I
  
        DO I = 1, N
           ARRAY( I ) = I
        END DO
  
        END
  
  
        SUBROUTINE PRNT( ARRAY, N )
  * Print the elements of ARRAY.
        INTEGER N, ARRAY( N )
        INTEGER I
  
        DO I = 1, N
           PRINT *,ARRAY( I )
        END DO
  
        END

In this case the main program merely sets the value of STATUS and calls the subroutine GETVM to do the work. Although this is more typing, it does have the advantage that this could be made into an ADAM task simply by deleting the main program. GETVM tests that the value of STATUS returned from PSX_CALLOC is OK, but does not print any error message. This is not necessary, as the PSX routines all report their own errors via the EMS routines. The reporting of error messages may be deferred if required, as described in SUN/104 and SSN/4.

If the code is required to work where pointers may be longer than INTEGERs, The construct %VAL(CNF_PVAL(PNTR)), rather than simply %VAL(PNTR), should be used in passing the pointer to FILL and PRNT. Function CNF_PVAL is defined in the CNF_PAR include file and described in SUN/209 (section ‘Pointers’).