/****************************************************************************
**  SIONLIB     http://www.fz-juelich.de/jsc/sionlib                       **
*****************************************************************************
**  Copyright (c) 2008-2009                                                **
**  Forschungszentrum Juelich, Juelich Supercomputing Centre               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/
#ifndef SION_FORTRAN_H_
#define SION_FORTRAN_H_

#ifdef SION_MPI
#include <mpi.h>
#endif

#include "sion.h"

/*!
 * @file sion_fortran.h
 * @brief Fortran API
 * @author Ventsislav Petkov
 * @date 14.08.2008
 */

/* sion_open() */
#if defined(_FORTRANCAPS)
#define fsion_open FSION_OPEN

#elif defined(_FORTRANNOCAPS)
#define fsion_open fsion_open

#elif defined(_FORTRANUNDERSCORE)
#define fsion_open fsion_open_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_open fsion_open__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_open(char *fname,
		char *file_mode,
		int  *ntasks,
		int  *nfiles,
		sion_int32  *fsblksize,
		int  *globalranks,
		int  *sid,
		long fname_len,
		long file_mode_len);

/* sion_open_rank() */
#if defined(_FORTRANCAPS)
#define fsion_open_rank FSION_OPEN_RANK

#elif defined(_FORTRANNOCAPS)
#define fsion_open_rank fsion_open_rank

#elif defined(_FORTRANUNDERSCORE)
#define fsion_open_rank fsion_open_rank_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_open_rank fsion_open_rank__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_open_rank(char *fname,
                     char *file_mode,
		     sion_int64 *chunksize,
		     sion_int32 *fsblksize,
		     int  *rank,
		     int  *sid,
		     long fname_len,
		     long file_mode_len);

#ifdef SION_MPI

/* sion_paropen_mpi() */
#if defined(_FORTRANCAPS)
#define fsion_paropen_mpi FSION_PAROPEN_MPI

#elif defined(_FORTRANNOCAPS)
#define fsion_paropen_mpi fsion_paropen_mpi

#elif defined(_FORTRANUNDERSCORE)
#define fsion_paropen_mpi fsion_paropen_mpi_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_paropen_mpi fsion_paropen_mpi__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_paropen_mpi(char *fname,
                       char *file_mode,
		       int  *numFiles,
                       MPI_Fint * fgComm,
                       MPI_Fint * flComm,
                       sion_int64 *chunksize, 
		       sion_int32 *fsblksize, 
		       int *globalrank, 
		       char *newfname,
		       int *sid, 
		       long fname_len, 
		       long file_mode_len,
		       long newfname_len);

/* sion_paropen_multi_mpi() */
#if defined(_FORTRANCAPS)
#define fsion_paropen_multi_mpi FSION_PAROPEN_MULTI_MPI

#elif defined(_FORTRANNOCAPS)
#define fsion_paropen_multi_mpi fsion_paropen_multi_mpi

#elif defined(_FORTRANUNDERSCORE)
#define fsion_paropen_multi_mpi fsion_paropen_multi_mpi_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_paropen_multi_mpi fsion_paropen_multi_mpi__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_paropen_multi_mpi(  char *fname,
                               char *file_mode,
                               int  *numFiles,
                               MPI_Fint *fgComm,
                               MPI_Fint *flComm,
                               sion_int64 *chunksize,
                               sion_int32 *fsblksize,
                               int  *globalrank,
                               int  *sid,
                               char *newfname,
                               long fname_len,
                               long file_mode_len,
                               long newfname_len);

/* sion_parclose_mpi() */
#if defined(_FORTRANCAPS)
#define fsion_parclose_mpi FSION_R

#elif defined(_FORTRANNOCAPS)
#define fsion_parclose_mpi fsion_parclose_mpi

#elif defined(_FORTRANUNDERSCORE)
#define fsion_parclose_mpi fsion_parclose_mpi_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_parclose_mpi fsion_parclose_mpi__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_parclose_mpi(int  *sid, int *ierr);

#endif

/* sion_close() */
#if defined(_FORTRANCAPS)
#define fsion_close FSION_CLOSE

#elif defined(_FORTRANNOCAPS)
#define fsion_close fsion_close

#elif defined(_FORTRANUNDERSCORE)
#define fsion_close fsion_close_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_close fsion_close__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_close(int *sid, int *ierr);

/* sion_feof() */
#if defined(_FORTRANCAPS)
#define fsion_feof FSION_FEOF

#elif defined(_FORTRANNOCAPS)
#define fsion_feof fsion_feof

#elif defined(_FORTRANUNDERSCORE)
#define fsion_feof fsion_feof_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_feof fsion_feof__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_feof( int *sid, int *eof);

/* sion_seek() */
#if defined(_FORTRANCAPS)
#define fsion_seek FSION_SEEK

#elif defined(_FORTRANNOCAPS)
#define fsion_seek fsion_seek

#elif defined(_FORTRANUNDERSCORE)
#define fsion_seek fsion_seek_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_seek fsion_seek__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_seek( int  *sid,
		 int  *rank,
		 int  *currentblocknr,
		 sion_int64 *posinblk,
		 int  *ierr);

/* sion_ensure_free_space() */
#if defined(_FORTRANCAPS)
#define fsion_ensure_free_space FSION_ENSURE_FREE_SPACE

#elif defined(_FORTRANNOCAPS)
#define fsion_ensure_free_space fsion_ensure_free_space

#elif defined(_FORTRANUNDERSCORE)
#define fsion_ensure_free_space fsion_ensure_free_space_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_ensure_free_space fsion_ensure_free_space__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_ensure_free_space(int *sid, sion_int64 *bytes, int *ierr);

/* sion_write() */
#if defined(_FORTRANCAPS)
#define fsion_write FSION_WRITE

#elif defined(_FORTRANNOCAPS)
#define fsion_write fsion_write

#elif defined(_FORTRANUNDERSCORE)
#define fsion_write fsion_write_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_write fsion_write__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_write(const void *data, int *size, sion_int64 *nitems, int *sid, sion_int64 *rc);

/* sion_flush() */
#if defined(_FORTRANCAPS)
#define fsion_flush FSION_FLUSH

#elif defined(_FORTRANNOCAPS)
#define fsion_flush fsion_flush

#elif defined(_FORTRANUNDERSCORE)
#define fsion_flush fsion_flush_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_flush fsion_flush__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_flush(int *sid, int *ierr);

/* sion_read() */
#if defined(_FORTRANCAPS)
#define fsion_read FSION_R

#elif defined(_FORTRANNOCAPS)
#define fsion_read fsion_read

#elif defined(_FORTRANUNDERSCORE)
#define fsion_read fsion_read_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_read fsion_read__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_read(void *data, int *size, sion_int64 *nitems, int *sid, sion_int64 *rc);

/* sion_bytes_avail_in_block() */
#if defined(_FORTRANCAPS)
#define fsion_bytes_avail_in_block FSION_BYTES_AVAIL_IN_BLOCK

#elif defined(_FORTRANNOCAPS)
#define fsion_bytes_avail_in_block fsion_bytes_avail_in_block

#elif defined(_FORTRANUNDERSCORE)
#define fsion_bytes_avail_in_block fsion_bytes_avail_in_block_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_bytes_avail_in_block fsion_bytes_avail_in_block__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
sion_int64 fsion_bytes_avail_in_block( int *sid);

/* sion_get_locations() */
#if defined(_FORTRANCAPS)
#define fsion_get_locations FSION_GET_LOCATIONS

#elif defined(_FORTRANNOCAPS)
#define fsion_get_locations fsion_get_locations

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_locations fsion_get_locations_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_locations fsion_get_locations__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_locations(int   *sid,
			 int   *ntasks,
			 int   *maxblocks,
			 sion_int64 *globalskip,
			 sion_int64 *start_of_varheader,
			 sion_int64 **sion_chunksizes,
			 sion_int64 **sion_globalranks,
			 sion_int64 **sion_blockcount,
			 sion_int64 **sion_fsblksizes,
			 int *ierr);


/* sion_get_current_location() */
#if defined(_FORTRANCAPS)
#define fsion_get_current_locations FSION_GET_CURRENT_LOCATION

#elif defined(_FORTRANNOCAPS)
#define fsion_get_current_locations fsion_get_current_location

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_current_locations fsion_get_current_location_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_current_locations fsion_get_current_location__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_current_locations(int   *sid,
				 int   *ntasks,
				 sion_int64 **sion_currentpos,
				 sion_int64 **sion_currentblocknr,
				 int *ierr);


/* sion_get_chunksizes() */
#if defined(_FORTRANCAPS)
#define fsion_get_chunksizes FSION_GET_CHUNKSIZES

#elif defined(_FORTRANNOCAPS)
#define fsion_get_chunksizes fsion_get_chunksizes

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_chunksizes fsion_get_chunksizes_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_chunksizes fsion_get_chunksizes__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_chunksizes(
			  int         *sid,
			  sion_int64  *chunksizes, 
			  int         *ierr);



/* sion_get_mapping_spec() */
#if defined(_FORTRANCAPS)
#define fsion_get_mapping_spec FSION_GET_MAPPING_SPEC

#elif defined(_FORTRANNOCAPS)
#define fsion_get_mapping_spec fsion_get_mapping_spec

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_mapping_spec fsion_get_mapping_spec_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_mapping_spec fsion_get_mapping_spec__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_mapping_spec(int         *sid,
			    int         *mapping_size, 
			    int         *numfiles, 
			    int         *ierr);

/* sion_get_mapping() */
#if defined(_FORTRANCAPS)
#define fsion_get_mapping FSION_GET_MAPPING

#elif defined(_FORTRANNOCAPS)
#define fsion_get_mapping fsion_get_mapping

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_mapping fsion_get_mapping_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_mapping fsion_get_mapping__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_mapping(int *sid, 
		       sion_int32 *mapping, 
		       int *ierr);

/* sion_get_position() */
#if defined(_FORTRANCAPS)
#define fsion_get_position FSION_GET_POSITION

#elif defined(_FORTRANNOCAPS)
#define fsion_get_position fsion_get_position

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_position fsion_get_position_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_position fsion_get_position__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
sion_int64 fsion_get_position( int *sid);

/* sion_get_position() */
#if defined(_FORTRANCAPS)
#define fsion_get_fileno FSION_GET_FILENO

#elif defined(_FORTRANNOCAPS)
#define fsion_get_fileno fsion_get_fileno

#elif defined(_FORTRANUNDERSCORE)
#define fsion_get_fileno fsion_get_fileno_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_get_fileno fsion_get_fileno__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_get_fileno(int *sid, int *filenumber);


/* sion_set_fp_closed() */
#if defined(_FORTRANCAPS)
#define fsion_set_fp_closed FSION_SET_FP_CLOSED

#elif defined(_FORTRANNOCAPS)
#define fsion_set_fp_closed fsion_set_fp_closed

#elif defined(_FORTRANUNDERSCORE)
#define fsion_set_fp_closed fsion_set_fp_closed_

#elif defined(_FORTRANDOUBLEUNDERSCORE)
#define fsion_set_fp_closed fsion_set_fp_closed__

#elif defined(_FORTRANNOUNDERSCORE)
#else
#error nothing defined for fortran externals
#endif
void fsion_set_fp_closed(int *sid, int *ierr);

/* endianness FIX */
#define SWAP_2(x) ( (((x) & 0xff) << 8) | ((unsigned short)(x) >> 8) )
#define SWAP_4(x) ( ((x) << 24) | (((x) << 8) & 0x00ff0000) | \
         (((x) >> 8) & 0x0000ff00) | ((x) >> 24) )
#define FIX_SHORT(x) (*(unsigned short *)&(x) = SWAP_2(*(unsigned short *)&(x)))
#define FIX_LONG(x) (*(unsigned *)&(x) = SWAP_4(*(unsigned *)&(x)))
#define FIX_FLOAT(x) FIX_LONG(x)

#endif /* SION_FORTRAN_H_ */
