/****************************************************************************
**  SCALASCA    http://www.scalasca.org/                                   **
*****************************************************************************
**  Copyright (c) 1998-2012                                                **
**  Forschungszentrum Juelich GmbH, Juelich Supercomputing Centre          **
**                                                                         **
**  Copyright (c) 2010-2012                                                **
**  German Research School for Simulation Sciences GmbH,                   **
**  Laboratory for Parallel Programming                                    **
**                                                                         **
**  Copyright (c) 2003-2008                                                **
**  University of Tennessee, Innovative Computing Laboratory               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/

/**
 * @file  epk_fmpiwrap_err.c
 *
 * @brief Fortran interface wrappers for error handling
 */

#include <stdlib.h>
#include <string.h>
#include <mpi.h>

#include "elg_error.h"
#include "elg_fmpi_defs.h"
#include "epk_fmpiwrap.h"
#include "epk_defs_mpi.h"
#include "epk_fwrapper_def.h"

/* uppercase defines */
/** All uppercase name of MPI_Add_error_class */
#define MPI_Add_error_class_U MPI_ADD_ERROR_CLASS
/** All uppercase name of MPI_Add_error_code */
#define MPI_Add_error_code_U MPI_ADD_ERROR_CODE
/** All uppercase name of MPI_Add_error_string */
#define MPI_Add_error_string_U MPI_ADD_ERROR_STRING
/** All uppercase name of MPI_Errhandler_create */
#define MPI_Errhandler_create_U MPI_ERRHANDLER_CREATE
/** All uppercase name of MPI_Errhandler_free */
#define MPI_Errhandler_free_U MPI_ERRHANDLER_FREE
/** All uppercase name of MPI_Errhandler_get */
#define MPI_Errhandler_get_U MPI_ERRHANDLER_GET
/** All uppercase name of MPI_Errhandler_set */
#define MPI_Errhandler_set_U MPI_ERRHANDLER_SET
/** All uppercase name of MPI_Error_class */
#define MPI_Error_class_U MPI_ERROR_CLASS
/** All uppercase name of MPI_Error_string */
#define MPI_Error_string_U MPI_ERROR_STRING

/* lowercase defines */
/** All lowercase name of MPI_Add_error_class */
#define MPI_Add_error_class_L mpi_add_error_class
/** All lowercase name of MPI_Add_error_code */
#define MPI_Add_error_code_L mpi_add_error_code
/** All lowercase name of MPI_Add_error_string */
#define MPI_Add_error_string_L mpi_add_error_string
/** All lowercase name of MPI_Errhandler_create */
#define MPI_Errhandler_create_L mpi_errhandler_create
/** All lowercase name of MPI_Errhandler_free */
#define MPI_Errhandler_free_L mpi_errhandler_free
/** All lowercase name of MPI_Errhandler_get */
#define MPI_Errhandler_get_L mpi_errhandler_get
/** All lowercase name of MPI_Errhandler_set */
#define MPI_Errhandler_set_L mpi_errhandler_set
/** All lowercase name of MPI_Error_class */
#define MPI_Error_class_L mpi_error_class
/** All lowercase name of MPI_Error_string */
#define MPI_Error_string_L mpi_error_string

/**
 * @name Fortran wrappers
 * @{
 */

#ifndef NEED_F2C_CONV

/* If MPI_Comm_f2c is defined as a simple macro (which typically does nothing)
 * as it would require a "real" function if it is really needed
 * => we can save the f2c and c2s conversions */

#if defined(HAS_MPI_ADD_ERROR_CLASS) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_class
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_class)(int* errorclass,
                               int* ierr)
{
  *ierr = MPI_Add_error_class(errorclass);
}

#endif
#if defined(HAS_MPI_ADD_ERROR_CODE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_code
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_code)(int* errorclass,
                              int* errorcode,
                              int* ierr)
{
  *ierr = MPI_Add_error_code(*errorclass, errorcode);
}

#endif
#if defined(HAS_MPI_ADD_ERROR_STRING) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_string
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_string)(int*  errorcode,
                                char* string,
                                int*  ierr,
                                int   string_len)
{
  char* c_string     = NULL;
  int   c_string_len = string_len;

  while ((c_string_len > 0) && (string[c_string_len - 1] == ' '))
  {
    c_string_len--;
  }
  c_string = (char*)malloc((string_len + 1) * sizeof (char));
  if (!c_string)
  {
    exit(EXIT_FAILURE);
  }
  strncpy(c_string, string, string_len);
  c_string[c_string_len] = '\0';

  *ierr = MPI_Add_error_string(*errorcode, c_string);

  free(c_string);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_CREATE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_create
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_create)(MPI_Handler_function* function,
                                 MPI_Errhandler*       errhandler,
                                 int*                  ierr)
{
  *ierr = MPI_Errhandler_create(function, errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_FREE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_free
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_free)(MPI_Errhandler* errhandler,
                               int*            ierr)
{
  *ierr = MPI_Errhandler_free(errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_GET) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_get
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_get)(MPI_Comm*       comm,
                              MPI_Errhandler* errhandler,
                              int*            ierr)
{
  *ierr = MPI_Errhandler_get(*comm, errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_SET) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_set
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_set)(MPI_Comm*       comm,
                              MPI_Errhandler* errhandler,
                              int*            ierr)
{
  *ierr = MPI_Errhandler_set(*comm, *errhandler);
}

#endif
#if defined(HAS_MPI_ERROR_CLASS) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Error_class
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Error_class)(int* errorcode,
                           int* errorclass,
                           int* ierr)
{
  *ierr = MPI_Error_class(*errorcode, errorclass);
}

#endif
#if defined(HAS_MPI_ERROR_STRING) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Error_string
 * @note Auto-generated by wrapgen from template: fstd.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Error_string)(int*  errorcode,
                            char* string,
                            int*  resultlen,
                            int*  ierr,
                            int   string_len)
{
  char* c_string     = NULL;
  int   c_string_len = 0;

  c_string = (char*)malloc((string_len + 1) * sizeof (char));
  if (!c_string)
  {
    exit(EXIT_FAILURE);
  }

  *ierr = MPI_Error_string(*errorcode, c_string, resultlen);

  c_string_len = strlen(c_string);
  strncpy(string, c_string, c_string_len);
  memset(string + c_string_len, ' ', string_len - c_string_len);
  free(c_string);
}

#endif

#else /* !NEED_F2C_CONV */

#if defined(HAS_MPI_ADD_ERROR_CLASS) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_class
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_class)(MPI_Fint* errorclass,
                               MPI_Fint* ierr)
{
  *ierr = MPI_Add_error_class(errorclass);
}

#endif
#if defined(HAS_MPI_ADD_ERROR_CODE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_code
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_code)(MPI_Fint* errorclass,
                              MPI_Fint* errorcode,
                              MPI_Fint* ierr)
{
  *ierr = MPI_Add_error_code(*errorclass, errorcode);
}

#endif
#if defined(HAS_MPI_ADD_ERROR_STRING) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Add_error_string
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 2.0
 * @ingroup err
 */
void FSUB(MPI_Add_error_string)(MPI_Fint* errorcode,
                                char*     string,
                                MPI_Fint* ierr,
                                int       string_len)
{
  char* c_string     = NULL;
  int   c_string_len = string_len;

  while ((c_string_len > 0) && (string[c_string_len - 1] == ' '))
  {
    c_string_len--;
  }
  c_string = (char*)malloc((string_len + 1) * sizeof (char));
  if (!c_string)
  {
    exit(EXIT_FAILURE);
  }
  strncpy(c_string, string, string_len);
  c_string[c_string_len] = '\0';

  *ierr = MPI_Add_error_string(*errorcode, c_string);

  free(c_string);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_CREATE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_create
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_create)(void*     function,
                                 void*     errhandler,
                                 MPI_Fint* ierr)
{
  *ierr =
    MPI_Errhandler_create((MPI_Handler_function*)function,
                          (MPI_Errhandler*)errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_FREE) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_free
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_free)(void*     errhandler,
                               MPI_Fint* ierr)
{
  *ierr = MPI_Errhandler_free((MPI_Errhandler*)errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_GET) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_get
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_get)(MPI_Fint* comm,
                              void*     errhandler,
                              MPI_Fint* ierr)
{
  *ierr = MPI_Errhandler_get(PMPI_Comm_f2c(
                               *comm), (MPI_Errhandler*)errhandler);
}

#endif
#if defined(HAS_MPI_ERRHANDLER_SET) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Errhandler_set
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Errhandler_set)(MPI_Fint* comm,
                              void*     errhandler,
                              MPI_Fint* ierr)
{
  *ierr =
    MPI_Errhandler_set(PMPI_Comm_f2c(*comm), *((MPI_Errhandler*)errhandler));
}

#endif
#if defined(HAS_MPI_ERROR_CLASS) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Error_class
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Error_class)(MPI_Fint* errorcode,
                           MPI_Fint* errorclass,
                           MPI_Fint* ierr)
{
  *ierr = MPI_Error_class(*errorcode, errorclass);
}

#endif
#if defined(HAS_MPI_ERROR_STRING) && !defined(NO_MPI_EXTRA) \
  && !defined(NO_MPI_ERR)
/**
 * Measurement wrapper for MPI_Error_string
 * @note Auto-generated by wrapgen from template: f2c_c2f.w
 * @note Fortran interface
 * @note Introduced with MPI 1.0
 * @ingroup err
 */
void FSUB(MPI_Error_string)(MPI_Fint* errorcode,
                            char*     string,
                            MPI_Fint* resultlen,
                            MPI_Fint* ierr,
                            int       string_len)
{
  char* c_string     = NULL;
  int   c_string_len = 0;

  c_string = (char*)malloc((string_len + 1) * sizeof (char));
  if (!c_string)
  {
    exit(EXIT_FAILURE);
  }

  *ierr = MPI_Error_string(*errorcode, c_string, resultlen);

  c_string_len = strlen(c_string);
  strncpy(string, c_string, c_string_len);
  memset(string + c_string_len, ' ', string_len - c_string_len);
  free(c_string);
}

#endif

#endif

/**
 * @}
 */
