/*
 * Copyright (c) 2005 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement
 * retains certain rights in this software.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *     * Neither the name of Sandia Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/*
 * OVERVIEW
 *
 * This file contains jacket routines written in C for interfacing Fortran
 * ExodusII function calls to the actual C binding for ExodusII.

 * In general, these functions handle
 * character-string parameter conventions, convert between
 * column-major-order arrays and row-major-order arrays, and map between
 * array indices beginning at one and array indices beginning at zero.
 *
 */

/* LINTLIBRARY */
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "netcdf.h"
#include "exodusII.h"
#include "exodusII_int.h"

/*
 * The Build64 is for the "normal" SEACAS build which uses compiler
 * options to change reals and integers into 8-byte quantities.  The
 * routines in addrwrap.F are used to down-convert the 8-byte integers
 * into 4-byte integers which then call through to the routines in
 * this file which have a '4' or '4_' appended to the routine name.
 * These routines then call through to the C API routines.
 *
 * If DEFAULT_REAL_INT is defined, then the build is to build a
 * fortran library interface that takes 4-byte ints and either 4-byte
 * or 8-byte floating point (real/double) variables. In this case, the
 * addrwrap routines are not built and a fortran client will call the
 * routines in this file directly.
 *
 */

#if defined(Build64) && !defined(DEFAULT_REAL_INT)
/* 64-bit */
#define real double
#define entity_id ex_entity_id
#ifdef ADDC_
#define F2C(name) name##4_
#else
#define F2C(name) name##4
#endif

#else
/* 32-bit */
#define real float
#define entity_id int
#ifdef ADDC_
#define F2C(name) name##_
#else
#define F2C(name) name
#endif
#endif

extern int      ncopts;         /* default is (NC_FATAL | NC_VERBOSE) */
extern int      exerrval;       /* global integer that contains a
                                 * Exodus-specific error code */

/* blank fill C string to make FORTRAN string */
static void
ex_fcdcpy(char *fstring,        /* output string to be blank-filled */
          int fslen,            /* length of output string */
          char *sstring)
{                               /* input string, null-terminated */
  int             i, len;

  if (sstring != NULL) {
    len = strlen(sstring);
    if (len > fslen)
      len = fslen;

    for (i = 0; i < len; i++)
      *(fstring + i) = *(sstring + i);
    for (i = len; i < fslen; i++)
      *(fstring + i) = ' ';
  } else {
    for (i = 0; i < fslen; i++)
      *(fstring + i) = ' ';
  }
}

/* copy function used to copy strings and strip trailing blanks */
static void
ex_fstrncpy(char *target,       /* space to be copied into */
            char *source,       /* string to be copied */
            int maxlen)
{                               /* maximum length of *source */
  int             len = maxlen;

  while (len-- && *source != '\0')
    *target++ = *source++;

  len = maxlen;
  while (len-- && *(--target) == ' ');  /* strip blanks */
  *(++target) = '\0';           /* insert new EOS marker */
}

/* copy function used to copy strings terminated with blanks */
static void
ex_nstrncpy(char *target,       /* space to be copied into */
            char *source,       /* string to be copied */
            int maxlen)
{                               /* maximum length of *source */
  while (maxlen-- && *source != ' ')
    *target++ = *source++;
  *target = '\0';
}

/* Above are utility functions used below                                   */
/* ======================================================================== */
/* Below are the exodus API functions                                       */
/*
 * Adding a new function:
 * +  Protect the name with the f2c (uppercase) macro which will add/not add '4' and or '_'
 *    depending on the compilation mode.
 *
 * +  float/double arguments are declared as 'real' which will be replaced with float or double.
 *
 * +  If there are any character arguments 'X', then add an int* argument 'Xlen' at end of argument list
 *    This will contain the length of the passed in character argument.
 *
 * +  Look at existing functions for guidance...
 */

/*
 * create an EXODUS II file
 */
int
F2C(excre) (char *path,
            int *clobmode,
            int *cpu_word_size,
            int *io_word_size,
            int *ierr,
            int pathlen)
{
  char           *name;
  int             idexo;

  if (!(name = malloc((pathlen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return (EX_FATAL);
  }
  (void) ex_nstrncpy(name, path, pathlen);

  if ((idexo = ex_create(name, *clobmode, cpu_word_size, io_word_size)) != EX_FATAL) {
    free(name);
    *ierr = 0;
    return (idexo);
  }
  free(name);
  *ierr = exerrval;
  return (EX_FATAL);
}

/*
 * open an EXODUS II file
 */
int
F2C(exopen) (char *path,
             int *mode,
             int *cpu_word_size,
             int *io_word_size,
             float *version,    /* This is float always; not real */
             int *ierr,
             int pathlen)
{
  char           *name;
  int             idexo;

  if (!(name = malloc((pathlen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return (EX_FATAL);
  }
  (void) ex_nstrncpy(name, path, pathlen);
  if ((idexo = ex_open(name, *mode, cpu_word_size, io_word_size, version)) != EX_FATAL) {
    free(name);
    *ierr = 0;
    return (idexo);
  }
  free(name);
  *ierr = EX_FATAL;
  return (EX_FATAL);
}

/*
 * close an EXODUS II file
 */
void
F2C(exclos) (int *idexo, int *ierr)
{
  *ierr = ex_close(*idexo);
}

/*
 * update an EXODUS II file
 */
void
F2C(exupda) (int *idexo, int *ierr)
{
  *ierr = ex_update(*idexo);
}

/*
 * write initialization parameters
 */
void
F2C(expini) (int *idexo,
             char *title,
             void_int *num_dim,
             void_int *num_nodes,
             void_int *num_elem,
             void_int *num_elem_blk,
             void_int *num_node_sets,
             void_int *num_side_sets,
             int *ierr,
             int titlelen)
{
  int             slen;
  char           *name;

  slen = MAX_LINE_LENGTH;       /* max line size */
  if (titlelen != MAX_LINE_LENGTH) {
    slen = titlelen;
  }
  name = malloc((slen + 1) * sizeof(char));
  (void) ex_fstrncpy(name, title, slen);

  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int64_t *n_dim 	 = num_dim;
    int64_t *n_nodes 	 = num_nodes;
    int64_t *n_elem  	 = num_elem;
    int64_t *n_elem_blk  = num_elem_blk;
    int64_t *n_node_sets = num_node_sets;
    int64_t *n_side_sets = num_side_sets;

    *ierr = ex_put_init(*idexo, name, *n_dim, *n_nodes, *n_elem,
			*n_elem_blk, *n_node_sets, *n_side_sets);
  } else {
    int *n_dim 	     = num_dim;
    int *n_nodes     = num_nodes;
    int *n_elem      = num_elem;
    int *n_elem_blk  = num_elem_blk;
    int *n_node_sets = num_node_sets;
    int *n_side_sets = num_side_sets;

    *ierr = ex_put_init(*idexo, name, *n_dim, *n_nodes, *n_elem,
			*n_elem_blk, *n_node_sets, *n_side_sets);
  }
  free(name);
}

/*
 * read initialization parameters
 */
void
F2C(exgini) (int *idexo,
             char *title,
             void_int *num_dim,
             void_int *num_nodes,
             void_int *num_elem,
             void_int *num_elem_blk,
             void_int *num_node_sets,
             void_int *num_side_sets,
             int *ierr,
             int titlelen)
{
  int             slen;
  char           *name;

  *ierr = 0;
  slen = MAX_LINE_LENGTH;       /* max line size */
  if (titlelen != MAX_LINE_LENGTH) {
    slen = titlelen;
  }
  name = malloc((slen + 1) * sizeof(char));
  memset(name, 0, slen + 1);

  *ierr = ex_get_init(*idexo, name, num_dim, num_nodes, num_elem, num_elem_blk,
                      num_node_sets, num_side_sets);

  ex_fcdcpy(title, slen, name);
  free(name);
}

/*
 * write QA records
 */
void
F2C(expqa) (int *idexo,
            int *num_qa_records,
            char *qa_record,
            int *ierr,
            int qa_recordlen)
{
  char            errmsg[MAX_ERR_LENGTH];
  char          **sptr;         /* internal string pointer array for malloc
                                 * use */
  int             i, ii, iii, slen, alen;

  *ierr = 0;                    /* default no errror */

  slen = MAX_STR_LENGTH;        /* max str size */
  if (qa_recordlen != MAX_STR_LENGTH) {
    slen = qa_recordlen;
  }
  alen = 4;                     /* qa records are 4 strings deep */

  /* Allocate space for the name ptr array */
  if (!(sptr = malloc(((*num_qa_records) * alen + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /*
   * Allocate space for each of the strings, where size = slen, place
   * ptr into str ptr array,  and Copy Fortran qa records to staging
   * space
   */
  iii = 0;                      /* offset counter */
  for (i = 0; i < *num_qa_records; i++) {
    for (ii = 0; ii < alen; ii++) {
      *(sptr + iii) = malloc((slen + 1) * sizeof(char));
      if (*(sptr + iii) == 0) {
        free(sptr);             /* free up array ptr space */
        *ierr = EX_MEMFAIL;
        sprintf(errmsg,
          "Error: failed to allocate space for qa record %d for file id %d",
                i, *idexo);
        ex_err("expqa", errmsg, EX_MEMFAIL);
        return;
      }
      /* copy fortran string into allocated space */
      ex_fstrncpy(*(sptr + iii), qa_record + iii * qa_recordlen, slen);
      iii++;                    /* bump char array pointer */
    }
  }
  *(sptr + iii) = 0;            /* set last pointer to null */

  if (ex_put_qa(*idexo, *num_qa_records, (void *) sptr) == EX_FATAL)
    *ierr = EX_FATAL;

  /* Free up the space we used */
  iii = 0;
  for (i = 0; i < *num_qa_records; i++) {
    for (ii = 0; ii < alen; ii++) {
      free(*(sptr + iii));      /* First free up string space */
      iii++;
    }
  }
  free(sptr);                   /* Then free up array ptr space */
}

/*
 * read QA records
 */
void
F2C(exgqa) (int *idexo,
            char *qa_record,
            int *ierr,
            int qa_recordlen)
{
  int             num_qa_records;
  char          **sptr;         /* internal string pointer array for malloc
                                 * use */
  int             i, ii, iii, slen, alen;

  *ierr = 0;                    /* default no errror */

  slen = MAX_STR_LENGTH;        /* max str size */
  if (qa_recordlen != MAX_STR_LENGTH) {
    slen = qa_recordlen;
  }
  alen = 4;                     /* qa records are 4 strings deep */

  /* do ExodusII C call to find out how many qa records are avail */
  num_qa_records = ex_inquire_int(*idexo, EX_INQ_QA);

  /* Allocate space for the QA string ptr array */
  if (!(sptr = malloc((num_qa_records * alen + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /*
   * Step 1: Allocate space for each of the strings, where size = slen,
   * place string ptr into str ptr array. Step 2: Call routine to get
   * qa records Step 3: Copy C qa records to passed Fortran array space
   */

  iii = 0;                      /* offset counter */
  for (i = 0; i < num_qa_records; i++) {        /* pointer allocation loop */
    for (ii = 0; ii < alen; ii++) {
      *(sptr + iii) = malloc((slen + 1) * sizeof(char));
      if (*(sptr + iii) == 0) {
        *ierr = EX_MEMFAIL;
        return;
      }
      iii++;                    /* bump char array pointer */
    }
  }
  *(sptr + iii) = 0;            /* null out last pointer */

  /* do ExodusII C call to get qa records */
  if (ex_get_qa(*idexo, (void *) sptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    return;
  }
  iii = 0;                      /* offset counter */
  for (i = 0; i < num_qa_records; i++) {        /* string copy loop */
    for (ii = 0; ii < alen; ii++) {
      /* copy fortran string into allocated space */
      ex_fcdcpy(qa_record + iii * qa_recordlen, slen, *(sptr + iii));
      iii++;                    /* bump char array pointer */
    }
  }

  /* Free up the space we used */
  iii = 0;
  for (i = 0; i < num_qa_records; i++) {
    for (ii = 0; ii < alen; ii++) {
      free(*(sptr + iii));      /* First free up string space */
      iii++;
    }
  }
  free(sptr);                   /* Then free up array ptr space */
}

/*
 * write information records
 */
void
F2C(expinf) (int *idexo,
             int *num_info,
             char *info,
             int *ierr,
             int infolen)
{
  char          **aptr;         /* internal string array pointer for malloc
                                 * use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             i, slen;

  *ierr = 0;                    /* default no errror */
  slen = MAX_LINE_LENGTH;       /* max str size */
  if (infolen != MAX_LINE_LENGTH) {
    slen = infolen;
  }
  /* Allocate space for the string ptr array */
  if (!(aptr = malloc(((*num_info) + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the info records */
  if (!(sptr = malloc(*num_info * (slen + 1) * sizeof(char)))) {
    free(aptr);                 /* Free up string ptr array */
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy Fortran info records to staging space */
  for (i = 0; i < *num_info; i++) {
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
    ex_fstrncpy(*(aptr + i), info + i * infolen, slen); /* copy string into
                                                         * buffer */
  }
  *(aptr + i) = 0;              /* null out last ptr */
  if (ex_put_info(*idexo, *num_info, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* Free up string staging area */
    free(aptr);                 /* Free up string ptr array */
    return;
  }
  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * read information records
 */
void
F2C(exginf) (int *idexo,
             char *info,
             int *ierr,
             int infolen)
{
  char          **aptr;         /* internal string array pointer for malloc
                                 * use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             i, slen, num_info;

  *ierr = 0;                    /* default no errror */

  /* do exodusII C call to find out how many info records are avail */
  num_info = ex_inquire_int(*idexo, EX_INQ_INFO);

  slen = MAX_LINE_LENGTH;       /* max str size */
  if (infolen != MAX_LINE_LENGTH) {
    slen = infolen;
  }
  /*
   * Step 1: Allocate space for string ptr array Step 2: Allocate space
   * for info record strings, and put pointers into str ptr array Step
   * 3: Do ExodusII call to get records Step 4: Copy strings into
   * passed Fortran buffer space
   */

  /* Allocate space for the string ptr array */
  if (!(aptr = malloc((num_info + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate block of space for info strings */
  if (!(sptr = malloc(num_info * (slen + 1) * sizeof(char)))) {
    free(aptr);                 /* Free up string ptr array */
    *ierr = EX_MEMFAIL;
    return;
  }
  for (i = 0; i < num_info; i++)/* Put pointers to the info records in ptr
                                 * array */
    *(aptr + i) = sptr + i * (slen + 1);        /* put ptr in string ptr
                                                 * array */
  *(aptr + i) = 0;              /* null out last pointer */

  /* Do exodusII call to get info records */
  if (ex_get_info(*idexo, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);
    free(aptr);
    return;
  }
  for (i = 0; i < num_info; i++) {      /* Copy Fortran info records to
                                         * staging space */
    ex_fcdcpy(info + i * infolen, slen, *(aptr + i));   /* copy string into
                                                         * buffer */
    /** printf("[exginf] rec: %d , %s\n",i,*(aptr+i)); **/
  }

  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */

}

/*
 * write nodal coordinates
 */
void
F2C(expcor) (int *idexo,
             real * x_coor,
             real * y_coor,
             real * z_coor,
             int *ierr)
{
  *ierr = ex_put_coord(*idexo, x_coor, y_coor, z_coor);
}

/*
 * read nodal coordinates
 */
void
F2C(exgcor) (int *idexo,
             real * x_coor,
             real * y_coor,
             real * z_coor,
             int *ierr)
{
  *ierr = ex_get_coord(*idexo, x_coor, y_coor, z_coor);
}

/*
 * write coordinate names
 */
void
F2C(expcon) (int *idexo,
             char *coord_names,
             int *ierr,
             int coord_nameslen)
{
  char          **aptr;         /* internal array of string pointers for
                                 * malloc use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             i, ndim, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (coord_nameslen < slen) {
    slen = coord_nameslen;
  }
  /* do ExodusII C call to find out how many dimensions  */
  ndim = ex_inquire_int(*idexo, EX_INQ_DIM);

  /* Allocate space for the name ptr array */
  if (!(aptr = malloc((ndim + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /*
   * Allocate a block of space for the strings, where size = slen,
   * place ptrs into str ptr array,  and Copy Fortran coordinate names
   * to staging space
   */

  if (!(sptr = malloc(ndim * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);
    return;
  }
  for (i = 0; i < ndim; i++) {
    *(aptr + i) = sptr + i * (slen + 1);
    /* copy fortran string into allocated space */
    ex_fstrncpy(*(aptr + i), coord_names + i * coord_nameslen, slen);
  }
  *(aptr + i) = 0;              /* set last pointer to null */

  if (ex_put_coord_names(*idexo, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  /* Free up the space we used */
  free(sptr);                   /* First free up string space */
  free(aptr);                   /* Then free up array ptr space */
}
/*
 * read coordinate names
 */
void
F2C(exgcon) (int *idexo,
             char *coord_names,
             int *ierr,
             int coord_nameslen)
{
  char          **aptr;         /* internal string array pointer for malloc
                                 * use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             ndim;
  int             i, slen;

  *ierr = 0;                    /* default no error */

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (coord_nameslen < slen) {
    slen = coord_nameslen;
  }
  /* do ExodusII C call to find out how many dimensions */
  ndim = ex_inquire_int(*idexo, EX_INQ_DIM);

  /* allocate memory to stage the coordinate name ptrs into */
  if (!(aptr = malloc((ndim + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* allocate a block of memory to stage the coordinate names into */
  if (!(sptr = malloc(ndim * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);                 /* free up array ptr space */
    return;
  }
  for (i = 0; i < ndim; i++) {  /* put pointers to staging space into ptr
                                 * array */
    *(aptr + i) = sptr + i * (slen + 1);
  }

  /* do ExodusII C call to get coord name records */
  if (ex_get_coord_names(*idexo, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up string space */
    free(aptr);                 /* free up array ptr space */
    return;
  }
  /* copy C strings to Fortran arrays */
  memset(coord_names, 0, ndim * coord_nameslen);
  for (i = 0; i < ndim; i++) {
    ex_fcdcpy(coord_names + i * coord_nameslen, slen, *(aptr + i));     /* copy and blank fill */
  }

  free(sptr);                   /* Free up string buffer space */
  free(aptr);                   /* Finally, free up array ptr space */
  return;
}

/*
 * write element order map
 */
void
F2C(expmap) (int *idexo,
             void_int *elem_map,
             int *ierr)
{
  *ierr = ex_put_map(*idexo, elem_map);
}

/*
 * read element order map
 */
void
F2C(exgmap) (int *idexo,
             void_int *elem_map,
             int *ierr)
{
  *ierr = ex_get_map(*idexo, elem_map);
}

/*
 * write concatenated element block parameters
 */
void
F2C(expclb) (int *idexo,
             void_int *elem_blk_id,
             char *elem_type,
             void_int *num_elem_this_blk,
             void_int *num_nodes_per_elem,
             void_int *num_attr,
             int *create_maps,
             int *ierr,
             int elem_typelen)
{
  size_t          num_elem_blk;

  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  size_t          i, slen;

  *ierr = 0;                    /* default no error */

  num_elem_blk = ex_inquire_int(*idexo, EX_INQ_ELEM_BLK);

  slen = MAX_STR_LENGTH;        /* max str size */
  if (elem_typelen != MAX_STR_LENGTH) {
    slen = elem_typelen;
  }
  /* allocate memory for pointer array */
  if (!(aptr = malloc((num_elem_blk + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* allocate memory to stage the element type name into */
  if (!(sptr = malloc(num_elem_blk * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy element type names from Fortran array to staging area */
  for (i = 0; i < num_elem_blk; i++) {
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
    ex_fstrncpy(*(aptr + i), elem_type + i * elem_typelen, slen);       /* copy string into
                                                                         * buffer */
  }
  *(aptr + i) = 0;              /* null out last ptr */

  if (ex_put_concat_elem_block(*idexo, elem_blk_id, aptr, num_elem_this_blk,
                  num_nodes_per_elem, num_attr, *create_maps) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);
  free(aptr);
}

/*
 * write element block parameters
 */
void
F2C(expelb) (int *idexo,
             entity_id *elem_blk_id,
             char *elem_type,
             void_int *num_elem_this_blk,
             void_int *num_nodes_per_elem,
             void_int *num_attr,
             int *ierr,
             int elem_typelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;                    /* default no error */

  slen = MAX_STR_LENGTH;        /* max str size */
  if (elem_typelen != MAX_STR_LENGTH) {
    slen = elem_typelen;
  }
  /* allocate memory to stage the element type name into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy element type names from Fortran array to staging area */
  ex_fstrncpy(sptr, elem_type, slen);

  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int64_t *n_elem_this_blk  = num_elem_this_blk;
    int64_t *n_nodes_per_elem = num_nodes_per_elem;
    int64_t *n_attr           = num_attr;

    *ierr = ex_put_elem_block(*idexo, *elem_blk_id, sptr, *n_elem_this_blk,
			      *n_nodes_per_elem, *n_attr);
  } else {
    int *n_elem_this_blk  = num_elem_this_blk;
    int *n_nodes_per_elem = num_nodes_per_elem;
    int *n_attr           = num_attr;

    *ierr = ex_put_elem_block(*idexo, *elem_blk_id, sptr, *n_elem_this_blk,
			      *n_nodes_per_elem, *n_attr);
  }
  free(sptr);
}

/*
 * read element block parameters
 */
void
F2C(exgelb) (int *idexo,
             entity_id *elem_blk_id,
             char *elem_type,
             void_int *num_elem_this_blk,
             void_int *num_nodes_per_elem,
             void_int *num_attr,
             int *ierr,
             int elem_typelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;

  slen = MAX_STR_LENGTH;        /* max str size */
  if (elem_typelen != MAX_STR_LENGTH) {
    slen = elem_typelen;
  }
  /* allocate memory to stage the element type names into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  if (ex_get_elem_block(*idexo, *elem_blk_id, sptr, num_elem_this_blk,
                        num_nodes_per_elem, num_attr) == EX_FATAL) {
    *ierr = EX_FATAL;
    return;
  }
  /* Copy element type name from staging area to Fortran array */
  memset(elem_type, 0, elem_typelen);
  ex_fcdcpy(elem_type, slen, sptr);
  free(sptr);

}

/*
 * read element blocks IDs
 */
void
F2C(exgebi) (int *idexo,
             void_int *elem_blk_ids,
             int *ierr)
{
  *ierr = ex_get_elem_blk_ids(*idexo, elem_blk_ids);
}

/*
 * write element block connectivity
 */
void
F2C(expelc) (int *idexo,
             entity_id *elem_blk_id,
             void_int *connect,
             int *ierr)
{
  *ierr = ex_put_elem_conn(*idexo, *elem_blk_id, connect);
}

/*
 * read element block connectivity
 */
void
F2C(exgelc) (int *idexo,
             entity_id *elem_blk_id,
             void_int *connect,
             int *ierr)
{
  *ierr = ex_get_elem_conn(*idexo, *elem_blk_id, connect);
}

/*
 * write entity count-per-polyhedra information for nsided block
 */
void
F2C(expecpp) (int *idexo,
              int *obj_type,
              entity_id *elem_blk_id,
              int *counts,
              int *ierr)
{
  *ierr = ex_put_entity_count_per_polyhedra(*idexo, (ex_entity_type) * obj_type, *elem_blk_id, counts);
}

/*
 * read entity count-per-polyhedra information for nsided block
 */
void
F2C(exgecpp) (int *idexo,
              int *obj_type,
              entity_id *elem_blk_id,
              int *counts,
              int *ierr)
{
  *ierr = ex_get_entity_count_per_polyhedra(*idexo, (ex_entity_type) * obj_type, *elem_blk_id, counts);
}

/*
 * write element block attributes
 */
void
F2C(expeat) (int *idexo,
             entity_id *elem_blk_id,
             real * attrib,
             int *ierr)
{
  *ierr = ex_put_elem_attr(*idexo, *elem_blk_id, attrib);
}


/*
 * read element block attributes
 */
void
F2C(exgeat) (int *idexo,
             entity_id *elem_blk_id,
             real * attrib,
             int *ierr)
{
  *ierr = ex_get_elem_attr(*idexo, *elem_blk_id, attrib);
}

/*
 * read element block attribute names
 */
void
F2C(exgean) (int *idexo,
             entity_id *elem_blk_id,
             int *num_attr,
             char *names,
             int *ierr,
             int nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (nameslen < slen) {
    slen = nameslen;
  }
  /* allocate memory to for pointer array */
  if (!(aptr = malloc((*num_attr + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_attr * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);                 /* Free up string ptr array */
    return;
  }
  for (i = 0; i < *num_attr; i++)
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
  *(aptr + i) = 0;              /* null out last ptr */

  *ierr = 0;
  if (ex_get_elem_attr_names(*idexo, *elem_blk_id, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up allocated space */
    free(aptr);
  }
  /* Copy Fortran names from staging space */
  memset(names, 0, *num_attr * nameslen);
  for (i = 0; i < *num_attr; i++) {
    ex_fcdcpy(names + i * nameslen, slen, *(aptr + i)); /* copy str into Fortran
                                                         * buffer */
  }

  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * write element block attribute names
 */
void
F2C(expean) (int *idexo,
             entity_id *elem_blk_id,
             int *num_attr,
             char *names,
             int *ierr,
             int nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (nameslen < slen) {
    slen = nameslen;
  }
  /* allocate memory to for pointer array */
  if (!(aptr = malloc((*num_attr + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_attr * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);                 /* Free up string ptr array */
    return;
  }
  /* Copy Fortran names to staging space */
  for (i = 0; i < *num_attr; i++) {
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
    ex_fstrncpy(*(aptr + i), names + i * nameslen, slen);       /* copy string into
                                                                 * buffer */
  }
  *(aptr + i) = 0;              /* null out last ptr */

  *ierr = 0;
  if (ex_put_elem_attr_names(*idexo, *elem_blk_id, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * write object names
 */
void
F2C(expnams) (int *idexo,
              int *type,
              int *num_obj,
              char *names,
              int *ierr,
              int nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (nameslen < slen) {
    slen = nameslen;
  }
  /* allocate memory for pointer array */
  if (!(aptr = malloc((*num_obj + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_obj * (slen + 1) * sizeof(char)))) {
    free(aptr);                 /* Free up string ptr array */
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy Fortran names to staging space */
  for (i = 0; i < *num_obj; i++) {
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
    ex_fstrncpy(*(aptr + i), names + i * nameslen, slen);       /* copy string into
                                                                 * buffer */
  }
  *(aptr + i) = 0;              /* null out last ptr */
  /* do ExodusII C call to write results variables names */
  if (ex_put_names(*idexo, (ex_entity_type) * type, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * read object names
 */
void
F2C(exgnams) (int *idexo,
              int *type,
              int *num_obj,
              char *names,
              int *ierr,
              int nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (nameslen < slen) {
    slen = nameslen;
  }
  /* allocate memory to for pointer array */
  if (!(aptr = malloc((*num_obj + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_obj * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);                 /* Free up string ptr array */
    return;
  }
  for (i = 0; i < *num_obj; i++)
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
  *(aptr + i) = 0;              /* null out last ptr */

  /* do ExodusII C call to read results variables names */
  if (ex_get_names(*idexo, (ex_entity_type) * type, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up allocated space */
    free(aptr);
    return;
  }
  /* Copy Fortran names from staging space */
  memset(names, 0, *num_obj * nameslen);
  for (i = 0; i < *num_obj; i++) {
    ex_fcdcpy(names + i * nameslen, slen, *(aptr + i)); /* copy str into Fortran
                                                         * buffer */
  }

  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * write property array names
 */
void
F2C(exppn) (int *idexo,
            int *obj_type,
            int *num_props,
            char *prop_names,
            int *ierr,
            int prop_nameslen)
{
  char          **aptr;         /* internal string array pointer for malloc
                                 * use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             i, slen;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (prop_nameslen < slen) {
    slen = prop_nameslen;
  }
  /* Allocate space for the name ptr array */
  if (!(aptr = malloc((*num_props + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /*
   * Allocate a block of space for the strings, where size = slen,
   * place ptrs into str ptr array,  and Copy Fortran coordinate names
   * to staging space
   */

  if (!(sptr = malloc((*num_props) * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);
    return;
  }
  for (i = 0; i < *num_props; i++) {
    *(aptr + i) = sptr + i * (slen + 1);
    /* copy fortran string into allocated space */
    ex_fstrncpy(*(aptr + i), prop_names + i * prop_nameslen, slen);
  }
  *(aptr + i) = 0;              /* set last pointer to null */

  if (ex_put_prop_names(*idexo, (ex_entity_type) * obj_type, *num_props, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  /* Free up the space we used */
  free(sptr);                   /* First free up string space */
  free(aptr);                   /* Then free up array ptr space */
}


/*
 * read property array names
 */
void
F2C(exgpn) (int *idexo,
            int *obj_type,
            char *prop_names,
            int *ierr,
            int prop_nameslen)
{
  char            errmsg[MAX_ERR_LENGTH];
  char          **aptr;         /* internal string array pointer for malloc
                                 * use */
  char           *sptr;         /* internal string pointer for malloc use */
  int             i, slen;
  ex_inquiry      inq_code;
  int             num_props;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (prop_nameslen < slen) {
    slen = prop_nameslen;
  }
  switch ((ex_entity_type) * obj_type) {
  case EX_ELEM_BLOCK:
    inq_code = EX_INQ_EB_PROP;
    break;
  case EX_NODE_SET:
    inq_code = EX_INQ_NS_PROP;
    break;
  case EX_SIDE_SET:
    inq_code = EX_INQ_SS_PROP;
    break;
  case EX_ELEM_MAP:
    inq_code = EX_INQ_EM_PROP;
    break;
  case EX_NODE_MAP:
    inq_code = EX_INQ_NM_PROP;
    break;
  default:
    exerrval = EX_BADPARAM;
    *ierr = EX_BADPARAM;
    sprintf(errmsg, "Error: object type %d not supported; file id %d",
            *obj_type, *idexo);
    ex_err("exgpn", errmsg, exerrval);
    return;
  }


  /* do ExodusII C call to find out how many properties */
  num_props = ex_inquire_int(*idexo, inq_code);

  /* Allocate space for the name ptr array */
  if (!(aptr = malloc((num_props + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /*
   * Allocate a block of space for the strings, where size = slen,
   * place ptrs into str ptr array,  and Copy Fortran coordinate names
   * to staging space
   */

  if (!(sptr = malloc(num_props * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);
    return;
  }
  memset(sptr, 0, num_props * (slen + 1));

  for (i = 0; i < num_props; i++)
    *(aptr + i) = sptr + i * (slen + 1);        /* put ptrs to staging space
                                                 * into ptr array */
  *(aptr + i) = 0;              /* set last pointer to null */

  /* do ExodusII C call to get property name records */
  if (ex_get_prop_names(*idexo, (ex_entity_type) * obj_type, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up string space */
    free(aptr);                 /* free up array ptr space */
    return;
  }
  /* copy C strings to Fortran arrays */
  memset(prop_names, 0, num_props * prop_nameslen);
  for (i = 0; i < num_props; i++) {
    ex_fcdcpy(prop_names + i * prop_nameslen, slen, *(aptr + i));       /* copy and blank fill */
  }

  /* Free up the space we used */
  free(sptr);                   /* First free up string space */
  free(aptr);                   /* Then free up array ptr space */
}

/*
 * write object property
 */
void
F2C(expp) (int *idexo,
           int *obj_type,
           entity_id *obj_id,
           char *prop_name,
           entity_id *value,
           int *ierr,
           int prop_namelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (prop_namelen < slen) {
    slen = prop_namelen;
  }
  /* allocate memory to stage the property name into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy property name from Fortran string to staging area */
  ex_fstrncpy(sptr, prop_name, slen);

  *ierr = ex_put_prop(*idexo, (ex_entity_type) * obj_type, *obj_id, sptr, *value);

  free(sptr);
}

/*
 * read object property
 */
void
F2C(exgp) (int *idexo,
           int *obj_type,
           entity_id *obj_id,
           char *prop_name,
           void_int *value,
           int *ierr,
           int prop_namelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (prop_namelen < slen) {
    slen = prop_namelen;
  }
  /* allocate memory to stage the property name into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
  }
  /* Copy property name from Fortran string to staging area */
  ex_fstrncpy(sptr, prop_name, slen);

  /* use exodusII C routine to get the property value */
  if (ex_get_prop(*idexo, (ex_entity_type) * obj_type, *obj_id, sptr, value) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);
}

/*
 * read object property array
 */
void
F2C(exgpa) (int *idexo,
            int *obj_type,
            char *prop_name,
            void_int *values,
            int *ierr,
            int prop_namelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (prop_namelen < slen) {
    slen = prop_namelen;
  }
  /* allocate memory to stage the property name into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
  }
  memset(sptr, 0, slen + 1);

  /* Copy property name from Fortran string to staging area */
  ex_fstrncpy(sptr, prop_name, slen);


  /* use exodusII C routine to get the values array */
  if (ex_get_prop_array(*idexo, (ex_entity_type) * obj_type, sptr, values) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);
}

/*
 * write object property array
 */
void
F2C(exppa) (int *idexo,
            int *obj_type,
            char *prop_name,
            void_int *values,
            int *ierr,
            int prop_namelen)
{
  char           *sptr;         /* internal string pointer for malloc use */
  int             slen;

  *ierr = 0;

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (prop_namelen < slen) {
    slen = prop_namelen;
  }
  /* allocate memory to stage the property name into */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
  }
  /* Copy property name from Fortran string to staging area */
  ex_fstrncpy(sptr, prop_name, slen);


  /* Use exodusII C routine to store the property values */
  if (ex_put_prop_array(*idexo, (ex_entity_type) * obj_type, sptr, values) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);
}

/*
 * write node set parameters
 */
void
F2C(expnp) (int *idexo,
            entity_id *node_set_id,
            void_int *num_nodes_in_set,
            void_int *num_dist_in_set,
            int *ierr)
{
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int64_t nnis = *(int64_t*)num_nodes_in_set;
    int64_t ndis = *(int64_t*)num_dist_in_set;
    *ierr = ex_put_node_set_param(*idexo, *node_set_id, nnis, ndis);
  } else {
    int nnis = *(int*)num_nodes_in_set;
    int ndis = *(int*)num_dist_in_set;
    *ierr = ex_put_node_set_param(*idexo, *node_set_id, nnis, ndis);
  }
}

/*
 * read node set parameters
 */
void
F2C(exgnp) (int *idexo,
            entity_id *node_set_id,
            void_int *num_nodes_in_set,
            void_int *num_dist_in_set,
            int *ierr)
{
  *ierr = ex_get_node_set_param(*idexo, *node_set_id, num_nodes_in_set, num_dist_in_set);
}

/*
 * write node set
 */
void
F2C(expns) (int *idexo,
            entity_id *node_set_id,
            void_int *node_set_node_list,
            int *ierr)
{
  *ierr = ex_put_node_set(*idexo, *node_set_id, node_set_node_list);
}

/*
 * write node set dist factors
 */
void
F2C(expnsd) (int *idexo,
             entity_id *node_set_id,
             real * node_set_dist_fact,
             int *ierr)
{
  *ierr = ex_put_node_set_dist_fact(*idexo, *node_set_id, node_set_dist_fact);
}

/*
 * read node set
 */
void
F2C(exgns) (int *idexo,
            entity_id *node_set_id,
            void_int *node_set_node_list,
            int *ierr)
{
  *ierr = ex_get_node_set(*idexo, *node_set_id, node_set_node_list);
}

/*
 * read node set dist factors
 */
void
F2C(exgnsd) (int *idexo,
             entity_id *node_set_id,
             real * node_set_dist_fact,
             int *ierr)
{
  *ierr = ex_get_node_set_dist_fact(*idexo, *node_set_id, node_set_dist_fact);
}


/*
 * read node sets IDs
 */
void
F2C(exgnsi) (int *idexo,
             void_int *node_set_ids,
             int *ierr)
{
  *ierr = ex_get_node_set_ids(*idexo, node_set_ids);
}

/*
 * write concatenated node sets
 */
void
F2C(expcns) (int *idexo,
             void_int *node_set_ids,
             void_int *num_nodes_per_set,
             void_int *num_dist_per_set,
             void_int *node_sets_node_index,
             void_int *node_sets_dist_index,
             void_int *node_sets_node_list,
             real * node_sets_dist_fact,
             int *ierr)
{
  size_t num_node_sets, i;
  int int_size;

  void_int *node_index_ptr, *dist_index_ptr;

  *ierr = 0;

  num_node_sets = ex_inquire_int(*idexo, EX_INQ_NODE_SETS);

  int_size = sizeof(int);
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int_size = sizeof(int64_t);
  }
  
  /* allocate memory for C node index array */
  if (!(node_index_ptr = malloc(num_node_sets * int_size))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* allocate memory for C dist factor index array */
  if (!(dist_index_ptr = malloc(num_node_sets * int_size))) {
    free(node_index_ptr);
    *ierr = EX_MEMFAIL;
    return;
  }

  if (int_size == sizeof(int64_t)) {
    for (i = 0; i < num_node_sets; i++) { /* change from 1-based to 0 index */
      ((int64_t*)node_index_ptr)[i] = ((int64_t*)node_sets_node_index)[i] - 1;
      ((int64_t*)dist_index_ptr)[i] = ((int64_t*)node_sets_dist_index)[i] - 1;
    }
  } else {
    for (i = 0; i < num_node_sets; i++) { /* change from 1-based to 0 index */
      ((int*)node_index_ptr)[i] = ((int*)node_sets_node_index)[i] - 1;
      ((int*)dist_index_ptr)[i] = ((int*)node_sets_dist_index)[i] - 1;
    }
  }

  *ierr = ex_put_concat_node_sets(*idexo, node_set_ids, num_nodes_per_set,
				  num_dist_per_set, node_index_ptr,
				  dist_index_ptr, node_sets_node_list,
				  node_sets_dist_fact);
  free(node_index_ptr);
  free(dist_index_ptr);
}

/*
 * read concatenated node sets
 */
void
F2C(exgcns) (int *idexo,
             void_int *node_set_ids,
             void_int *num_nodes_per_set,
             void_int *num_dist_per_set,
             void_int *node_sets_node_index,
             void_int *node_sets_dist_index,
             void_int *node_sets_node_list,
             real * node_sets_dist_fact,
             int *ierr)
{
  size_t num_node_sets, i;

  *ierr = ex_get_concat_node_sets(*idexo, node_set_ids, num_nodes_per_set,
				  num_dist_per_set, node_sets_node_index,
				  node_sets_dist_index, node_sets_node_list,
				  node_sets_dist_fact);

  num_node_sets = ex_inquire_int(*idexo, EX_INQ_NODE_SETS);

  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    for (i = 0; i < num_node_sets; i++) { /* change from 0-based to 1 index */
      ((int64_t*)node_sets_node_index)[i] += 1;
      ((int64_t*)node_sets_dist_index)[i] += 1;
    }
  } else {
    for (i = 0; i < num_node_sets; i++) { /* change from 0-based to 1 index */
      ((int*)node_sets_node_index)[i] += 1;
      ((int*)node_sets_dist_index)[i] += 1;
    }
  }
}

/*
 * write side set parameters
 */
void
F2C(expsp) (int *idexo,
            entity_id *side_set_id,
            void_int *num_sides_in_set,
            void_int *num_df_in_set,
            int *ierr)
{
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int64_t nsis = *(int64_t*)num_sides_in_set;
    int64_t ndis = *(int64_t*)num_df_in_set;
    *ierr = ex_put_side_set_param(*idexo, *side_set_id, nsis, ndis);
  } else {
    int nsis = *(int*)num_sides_in_set;
    int ndis = *(int*)num_df_in_set;
    *ierr = ex_put_side_set_param(*idexo, *side_set_id, nsis, ndis);
  }
}

/*
 * read side set parameters
 */
void
F2C(exgsp) (int *idexo,
            entity_id *side_set_id,
            void_int *num_sides_in_set,
            void_int *num_df_in_set,
            int *ierr)
{
  *ierr = ex_get_side_set_param(*idexo, *side_set_id, num_sides_in_set, num_df_in_set);
}

/*
 * get side set node list length
 */
void
F2C(exgsnl) (int *idexo,
             entity_id *side_set_id,
             void_int *num_nodes_in_set,
             int *ierr)
{
  *ierr = ex_get_side_set_node_list_len(*idexo, *side_set_id, num_nodes_in_set);
}

/*
 * write side set
 */
void
F2C(expss) (int *idexo,
            entity_id *side_set_id,
            void_int *side_set_elem_list,
            void_int *side_set_side_list,
            int *ierr)
{
  *ierr = ex_put_side_set(*idexo, *side_set_id, side_set_elem_list, side_set_side_list);
}

/*
 * read side set
 */
void
F2C(exgss) (int *idexo,
            entity_id *side_set_id,
            void_int *side_set_elem_list,
            void_int *side_set_side_list,
            int *ierr)
{
  *ierr = ex_get_side_set(*idexo, *side_set_id, side_set_elem_list, side_set_side_list);
}

/*
 * write side set distribution factors
 */
void
F2C(expssd) (int *idexo,
             entity_id *side_set_id,
             real * side_set_dist_fact,
             int *ierr)
{
  *ierr = ex_put_side_set_dist_fact(*idexo, *side_set_id, side_set_dist_fact);
}

/*
 * read side set distribution factors
 */
void
F2C(exgssd) (int *idexo,
             entity_id *side_set_id,
             real * side_set_dist_fact,
             int *ierr)
{
  *ierr = ex_get_side_set_dist_fact(*idexo, *side_set_id, side_set_dist_fact);
}

/*
 * read side sets IDs
 */
void
F2C(exgssi) (int *idexo,
             void_int *side_set_ids,
             int *ierr)
{
  *ierr = ex_get_side_set_ids(*idexo, side_set_ids);
}

/*
 * write concatenated side sets
 */
void
F2C(expcss) (int *idexo,
             void_int *side_set_ids,
             void_int *num_elem_per_set,
             void_int *num_dist_per_set,
             void_int *side_sets_elem_index,
             void_int *side_sets_dist_index,
             void_int *side_sets_elem_list,
             void_int *side_sets_side_list,
             real * side_sets_dist_fact,
             int *ierr)
{
  size_t num_side_sets, i;
  void_int *elem_index_ptr, *dist_index_ptr;
  int int_size;

  *ierr = 0;

  num_side_sets = ex_inquire_int(*idexo, EX_INQ_SIDE_SETS);

  int_size = sizeof(int);
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    int_size = sizeof(int64_t);
  }

  /* allocate memory for C element index array */
  if (!(elem_index_ptr = malloc(num_side_sets * int_size))) {
    *ierr = EX_MEMFAIL;
    return;
  }

  /* allocate memory for C dist factor index array */
  if (!(dist_index_ptr = malloc(num_side_sets * int_size))) {
    free(elem_index_ptr);
    *ierr = EX_MEMFAIL;
    return;
  }

  if (int_size == sizeof(int64_t)) {
    for (i = 0; i < num_side_sets; i++) { /* change from 1-based to 0 index */
      ((int64_t*)elem_index_ptr)[i] = ((int64_t*)side_sets_elem_index)[i] - 1;
      ((int64_t*)dist_index_ptr)[i] = ((int64_t*)side_sets_dist_index)[i] - 1;
    }
  } else {
    for (i = 0; i < num_side_sets; i++) { /* change from 1-based to 0 index */
      ((int*)elem_index_ptr)[i] = ((int*)side_sets_elem_index)[i] - 1;
      ((int*)dist_index_ptr)[i] = ((int*)side_sets_dist_index)[i] - 1;
    }
  }

  *ierr = ex_put_concat_side_sets(*idexo, side_set_ids, num_elem_per_set,
				  num_dist_per_set, elem_index_ptr,
				  dist_index_ptr, side_sets_elem_list,
				  side_sets_side_list, side_sets_dist_fact);
  free(elem_index_ptr);
  free(dist_index_ptr);
}

/*
 * read concatenated side sets
 */
void
F2C(exgcss) (int *idexo,
             void_int *side_set_ids,
             void_int *num_elem_per_set,
             void_int *num_dist_per_set,
             void_int *side_sets_elem_index,
             void_int *side_sets_dist_index,
             void_int *side_sets_elem_list,
             void_int *side_sets_side_list,
             real * side_sets_dist_fact,
             int *ierr)
{
  size_t i, num_side_sets;

  *ierr = 0;

  num_side_sets = ex_inquire_int(*idexo, EX_INQ_SIDE_SETS);

  *ierr = ex_get_concat_side_sets(*idexo, side_set_ids, num_elem_per_set,
				  num_dist_per_set, side_sets_elem_index,
				  side_sets_dist_index, side_sets_elem_list,
				  side_sets_side_list, side_sets_dist_fact);

  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    for (i = 0; i < num_side_sets; i++) { /* change from 0-based to 1 index */
      ((int64_t*)side_sets_elem_index)[i] += 1;
      ((int64_t*)side_sets_dist_index)[i] += 1;
    }
  } else {
    for (i = 0; i < num_side_sets; i++) { /* change from 0-based to 1 index */
      ((int*)side_sets_elem_index)[i] += 1;
      ((int*)side_sets_dist_index)[i] += 1;
    }
  }
}

/*
 * read concatenated side sets (no dist factors)
 */
void
F2C(exgcssf) (int *idexo,
              void_int *side_set_ids,
              void_int *num_elem_per_set,
              void_int *num_dist_per_set,
              void_int *side_sets_elem_index,
              void_int *side_sets_dist_index,
              void_int *side_sets_elem_list,
              void_int *side_sets_side_list,
              int *ierr)
{
  size_t i, num_side_sets;

  num_side_sets = ex_inquire_int(*idexo, EX_INQ_SIDE_SETS);

  *ierr = ex_get_concat_side_sets(*idexo, side_set_ids, num_elem_per_set,
				  num_dist_per_set, side_sets_elem_index,
				  side_sets_dist_index, side_sets_elem_list,
				  side_sets_side_list, 0);

  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    for (i = 0; i < num_side_sets; i++) { /* change from 0-based to 1 index */
      ((int64_t*)side_sets_elem_index)[i] += 1;
      ((int64_t*)side_sets_dist_index)[i] += 1;
    }
  } else {
    for (i = 0; i < num_side_sets; i++) { /* change from 0-based to 1 index */
      ((int*)side_sets_elem_index)[i] += 1;
      ((int*)side_sets_dist_index)[i] += 1;
    }
  }
}

/*
 * write results variables parameters
 */
void
F2C(expvp) (int *idexo,
            char *var_type,
            int *num_vars,
            int *ierr,
            int var_typelen)
{
  *ierr = ex_put_var_param(*idexo, var_type, *num_vars);
}

/*
 * read results variables parameters
 */
void
F2C(exgvp) (int *idexo,
            char *var_type,
            int *num_vars,
            int *ierr,
            int var_typelen)
{
  *ierr = ex_get_var_param(*idexo, var_type, num_vars);
}

/*
 * write results variables names
 */
void
F2C(expvan) (int *idexo,
             char *var_type,
             int *num_vars,
             char *var_names,
             int *ierr,
             int var_typelen,
             int var_nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (var_nameslen < slen) {
    slen = var_nameslen;
  }
  /* allocate memory for pointer array */
  if (!(aptr = malloc((*num_vars + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_vars * (slen + 1) * sizeof(char)))) {
    free(aptr);                 /* Free up string ptr array */
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Copy Fortran variable names to staging space */
  for (i = 0; i < *num_vars; i++) {
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
    ex_fstrncpy(*(aptr + i), var_names + i * var_nameslen, slen);       /* copy string into
                                                                         * buffer */
  }
  *(aptr + i) = 0;              /* null out last ptr */
  /* do ExodusII C call to write results variables names */
  if (ex_put_var_names(*idexo, var_type, *num_vars, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
  }
  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}
/*
 * read results variables names
 */
void
F2C(exgvan) (int *idexo,
             char *var_type,
             int *num_vars,
             char *var_names,
             int *ierr,
             int var_typelen,
             int var_nameslen)
{
  char          **aptr;         /* ptr to temp staging space for string array
                                 * ptrs */
  char           *sptr;         /* ptr to temp staging space for strings */
  int             i, slen;

  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (var_nameslen < slen) {
    slen = var_nameslen;
  }
  /* allocate memory to for pointer array */
  if (!(aptr = malloc((*num_vars + 1) * sizeof(char *)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* Allocate staging space for the variable names */
  if (!(sptr = malloc(*num_vars * (slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    free(aptr);                 /* Free up string ptr array */
    return;
  }
  for (i = 0; i < *num_vars; i++)
    *(aptr + i) = sptr + i * (slen + 1);        /* put address into ptr array */
  *(aptr + i) = 0;              /* null out last ptr */

  /* do ExodusII C call to read results variables names */
  if (ex_get_var_names(*idexo, var_type, *num_vars, aptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up allocated space */
    free(aptr);
    return;
  }
  /* Copy Fortran variable names to staging space */
  memset(var_names, 0, *num_vars * var_nameslen);
  for (i = 0; i < *num_vars; i++) {
    ex_fcdcpy(var_names + i * var_nameslen, slen, *(aptr + i)); /* copy str into Fortran
                                                                 * buffer */
  }

  free(sptr);                   /* Free up string staging area */
  free(aptr);                   /* Free up string ptr array */
}

/*
 * write element variable truth table
 */
void
F2C(expvtt) (int *idexo,
             int *num_elem_blk,
             int *num_elem_var,
             int *elem_var_tab,
             int *ierr)
{
  *ierr = ex_put_elem_var_tab(*idexo, *num_elem_blk, *num_elem_var, elem_var_tab);
}

/*
 * write nodeset variable truth table
 */
void
F2C(expnstt) (int *idexo,
              int *num_entity,
              int *num_var,
              int *var_tab,
              int *ierr)
{
  *ierr = ex_put_nset_var_tab(*idexo, *num_entity, *num_var, var_tab);
}

/*
 * write sideset variable truth table
 */
void
F2C(expsstt) (int *idexo,
              int *num_entity,
              int *num_var,
              int *var_tab,
              int *ierr)
{
  *ierr = ex_put_sset_var_tab(*idexo, *num_entity, *num_var, var_tab);
}

/*
 * read element variable truth table
 */
void
F2C(exgvtt) (int *idexo,
             int *num_elem_blk,
             int *num_elem_var,
             int *elem_var_tab,
             int *ierr)
{
  *ierr = ex_get_elem_var_tab(*idexo, *num_elem_blk, *num_elem_var, elem_var_tab);
}

/*
 * read nodeset variable truth table
 */
void
F2C(exgnstt) (int *idexo,
              int *num_entity,
              int *num_var,
              int *var_tab,
              int *ierr)
{
  *ierr = ex_get_nset_var_tab(*idexo, *num_entity, *num_var, var_tab);
}

/*
 * read sideset variable truth table
 */
void
F2C(exgsstt) (int *idexo,
              int *num_entity,
              int *num_var,
              int *var_tab,
              int *ierr)
{
  *ierr = ex_get_sset_var_tab(*idexo, *num_entity, *num_var, var_tab);
}

/*
 * write global variable values at time step
 */
void
F2C(expgv) (int *idexo,
            int *time_step,
            int *num_glob_vars,
            real * glob_var_vals,
            int *ierr)
{
  *ierr = ex_put_glob_vars(*idexo, *time_step, *num_glob_vars, glob_var_vals);
}

/*
 * read global variable values at a time step
 */
void
F2C(exggv) (int *idexo,
            int *time_step,
            int *num_glob_vars,
            real * glob_var_vals,
            int *ierr)
{
  *ierr = ex_get_glob_vars(*idexo, *time_step, *num_glob_vars, glob_var_vals);
}

/*
 * read global variable values through time
 */
void
F2C(exggvt) (int *idexo,
             int *glob_var_index,
             int *beg_time_step,
             int *end_time_step,
             real * glob_var_vals,
             int *ierr)
{
  *ierr = ex_get_glob_var_time(*idexo, *glob_var_index, *beg_time_step, *end_time_step, glob_var_vals);
}

/*
 * write nodal variable values at a time step
 */
void
F2C(expnv) (int *idexo,
            int *time_step,
            int *nodal_var_index,
            void_int *num_nodes,
            real * nodal_var_vals,
            int *ierr)
{
  int64_t nnodes;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    nnodes = *(int64_t*)num_nodes;
  } else {
    nnodes = *(int*)num_nodes;
  }
  
  *ierr = ex_put_nodal_var(*idexo, *time_step, *nodal_var_index, nnodes, nodal_var_vals);
}

/*
 * read nodal variable values at a time step
 */
void
F2C(exgnv) (int *idexo,
            int *time_step,
            int *nodal_var_index,
            void_int *num_nodes,
            real * nodal_var_vals,
            int *ierr)
{
  int64_t nnodes;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    nnodes = *(int64_t*)num_nodes;
  } else {
    nnodes = *(int*)num_nodes;
  }
  
  *ierr = ex_get_nodal_var(*idexo, *time_step, *nodal_var_index, nnodes, nodal_var_vals);
}

/*
 * read nodal variable values through time
 */
void
F2C(exgnvt) (int *idexo,
             int *nodal_var_index,
             void_int *node_number,
             int *beg_time_step,
             int *end_time_step,
             real * nodal_var_vals,
             int *ierr)
{
  int64_t nnode;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    nnode = *(int64_t*)node_number;
  } else {
    nnode = *(int*)node_number;
  }
  
  *ierr = ex_get_nodal_var_time(*idexo, *nodal_var_index, nnode, *beg_time_step, *end_time_step, nodal_var_vals);
}

/*
 * write element variable values at a time step
 */
void
F2C(expev) (int *idexo,
            int *time_step,
            int *elem_var_index,
            entity_id *elem_blk_id,
            void_int *num_elem_this_blk,
            real * elem_var_vals,
            int *ierr)
{
  int64_t neblk;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    neblk = *(int64_t*)num_elem_this_blk;
  } else {
    neblk = *(int*)num_elem_this_blk;
  }
  
  *ierr = ex_put_elem_var(*idexo, *time_step, *elem_var_index, *elem_blk_id, neblk, elem_var_vals);
}

/*
 * read element variable values at a time step
 */
void
F2C(exgev) (int *idexo,
            int *time_step,
            int *elem_var_index,
            entity_id *elem_blk_id,
            void_int *num_elem_this_blk,
            real * elem_var_vals,
            int *ierr)
{
  int64_t neblk;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    neblk = *(int64_t*)num_elem_this_blk;
  } else {
    neblk = *(int*)num_elem_this_blk;
  }
  
  *ierr = ex_get_elem_var(*idexo, *time_step, *elem_var_index, *elem_blk_id, neblk, elem_var_vals);
}

/*
 * read element variable values through time
 */
void
F2C(exgevt) (int *idexo,
             int *elem_var_index,
             void_int *elem_number,
             int *beg_time_step,
             int *end_time_step,
             real * elem_var_vals,
             int *ierr)
{
  int64_t el_num;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    el_num = *(int64_t*)elem_number;
  } else {
    el_num = *(int*)elem_number;
  }
  
  *ierr = ex_get_elem_var_time(*idexo, *elem_var_index, el_num, *beg_time_step, *end_time_step, elem_var_vals);
}

/*
 * write nodeset variable values at a time step
 */
void
F2C(expnsv) (int *idexo,
             int *time_step,
             int *var_index,
             entity_id *id,
             void_int *num_entity,
             real * var_vals,
             int *ierr)
{
  int64_t n_entity;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    n_entity = *(int64_t*)num_entity;
  } else {
    n_entity = *(int*)num_entity;
  }
  
  *ierr = ex_put_nset_var(*idexo, *time_step, *var_index, *id, n_entity, var_vals);
}

/*
 * read nodeset variable values at a time step
 */
void
F2C(exgnsv) (int *idexo,
             int *time_step,
             int *var_index,
             entity_id *id,
             void_int *num_entity,
             real * var_vals,
             int *ierr)
{
  int64_t n_entity;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    n_entity = *(int64_t*)num_entity;
  } else {
    n_entity = *(int*)num_entity;
  }
  
  *ierr = ex_get_nset_var(*idexo, *time_step, *var_index, *id, n_entity, var_vals);
}

/*
 * write sideset variable values at a time step
 */
void
F2C(expssv) (int *idexo,
             int *time_step,
             int *var_index,
             entity_id *id,
             void_int *num_entity,
             real * var_vals,
             int *ierr)
{
  int64_t n_entity;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    n_entity = *(int64_t*)num_entity;
  } else {
    n_entity = *(int*)num_entity;
  }
  
  *ierr = ex_put_sset_var(*idexo, *time_step, *var_index, *id, n_entity, var_vals);
}

/*
 * read sideset variable values at a time step
 */
void
F2C(exgssv) (int *idexo,
             int *time_step,
             int *var_index,
             entity_id *id,
             void_int *num_entity,
             real * var_vals,
             int *ierr)
{
  int64_t n_entity;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    n_entity = *(int64_t*)num_entity;
  } else {
    n_entity = *(int*)num_entity;
  }
  
  *ierr = ex_get_sset_var(*idexo, *time_step, *var_index, *id, n_entity, var_vals);
}

/*
 * write time value for a time step
 */
void
F2C(exptim) (int *idexo,
             int *time_step,
             real * time_value,
             int *ierr)
{
  *ierr = ex_put_time(*idexo, *time_step, time_value);
}

/*
 * read time value for a time step
 */
void
F2C(exgtim) (int *idexo,
             int *time_step,
             real * time_value,
             int *ierr)
{
  *ierr = ex_get_time(*idexo, *time_step, time_value);
}

/*
 * read all time values
 */
void
F2C(exgatm) (int *idexo,
             real * time_values,
             int *ierr)
{
  *ierr = ex_get_all_times(*idexo, time_values);
}

/*
 * inquire EXODUS parameters
 */
void
F2C(exinq) (int *idexo,
            int *req_info,
            void_int *ret_int,
            float *ret_float,
            char *ret_char,
            int *ierr,
            int ret_charlen)
{
  *ierr = ex_inquire(*idexo, (ex_inquiry) * req_info, ret_int, ret_float, ret_char);
}

/*
 * inquire integer EXODUS parameters
 */
int64_t
F2C(exinqi) (int *idexo,
            int *req_info)
{
  return ex_inquire_int(*idexo, (ex_inquiry) *req_info);
}

/*
 * convert side set node lists to side set side lists
 */
void
F2C(excn2s) (int *idexo,
             void_int *num_elem_per_set,
             void_int *num_nodes_per_set,
             void_int *side_sets_elem_index,
             void_int *side_sets_node_index,
             void_int *side_sets_elem_list,
             void_int *side_sets_node_list,
             void_int *side_sets_side_list,
             int *ierr)
{
  *ierr = ex_cvt_nodes_to_sides(*idexo,
				num_elem_per_set,
				num_nodes_per_set,
				NULL, /* unused */
				NULL, /* unused */
				side_sets_elem_list,
				side_sets_node_list,
				side_sets_side_list);
}

/*
 * read side set node list
 */
void
F2C(exgssn) (int *idexo,
             entity_id *side_set_id,
             int *side_set_node_cnt_list,
             void_int *side_set_node_list,
             int *ierr)
{
  *ierr = ex_get_side_set_node_list(*idexo, *side_set_id, side_set_node_cnt_list, side_set_node_list);
}

/*
 * read side set node count
 */
void
F2C(exgssc) (int *idexo,
             entity_id *side_set_id,
             int *side_set_node_cnt_list,
             int *ierr)
{
  *ierr = ex_get_side_set_node_count(*idexo, *side_set_id, side_set_node_cnt_list);
}

/*
 * read concatenated side set node count
 */
void
F2C(exgcssc) (int *idexo,
              int *side_set_node_cnt_list,
              int *ierr)
{
  *ierr = ex_get_concat_side_set_node_count(*idexo, side_set_node_cnt_list);
}

/* ex_get_coordinate_frames -- read coordinate frames */
void
F2C(exgfrm) (int *idexo,
             int *nframeo,
             void_int *cfids,
             real * coord,
             int *tags,
             int *ierr)
{
  int             i;
  char           *ctags = NULL;

  /* Determine number of coordinate frames stored in file */
  int             nframe = ex_inquire_int(*idexo, EX_INQ_COORD_FRAMES);

  if (nframe != *nframeo) {
    *ierr = EX_FATAL;
    return;
  }
  /* Create array of characters to store tags... */
  if (nframe > 0) {
    if (!(ctags = calloc(nframe, sizeof(char)))) {
      *ierr = EX_MEMFAIL;
      return;
    }
    *ierr = 0;

    if (ex_get_coordinate_frames(*idexo, &nframe, cfids, coord, ctags) == EX_FATAL) {
      *ierr = EX_FATAL;
      return;
    }
    /* Convert character tags back to integer tags for fortran */
    for (i = 0; i < nframe; i++) {
      if (ctags[i] == 'R' || ctags[i] == 'r')
        tags[i] = EX_CF_RECTANGULAR;
      else if (ctags[i] == 'C' || ctags[i] == 'c')
        tags[i] = EX_CF_CYLINDRICAL;
      else if (ctags[i] == 'S' || ctags[i] == 's')
        tags[i] = EX_CF_SPHERICAL;
    }
    free(ctags);
  }
}

/* ex_put_coordinate_frames -- define/write coordinate frames */
void
F2C(expfrm) (int *idexo,
             int *nframe,
             void_int *cfids,
             real * coord,
             int *tags,
             int *ierr)
{
  int             i;
  char           *ctags = NULL;

  /* Create array of characters to store tags... */
  if (*nframe > 0) {
    if (!(ctags = calloc(*nframe, sizeof(char)))) {
      *ierr = EX_MEMFAIL;
      return;
    }
    /* Convert fortran integer tags to C API character tags */
    for (i = 0; i < *nframe; i++) {
      if (tags[i] == EX_CF_RECTANGULAR)
        ctags[i] = 'R';
      else if (tags[i] == EX_CF_CYLINDRICAL)
        ctags[i] = 'C';
      else if (tags[i] == EX_CF_SPHERICAL)
        ctags[i] = 'S';
    }

    *ierr = 0;

    if (ex_put_coordinate_frames(*idexo, *nframe, cfids, coord, ctags) == EX_FATAL) {
      *ierr = EX_FATAL;
      return;
    }
    free(ctags);
  }
}


/* Routine to return floating point word size */
int
F2C(excpws) ()
{
  return (ex_get_cpu_ws());
}

/* Routine to return large model setting */
int
F2C(exlgmd) (int *idexo)
{
  return (ex_large_model(*idexo));
}


/* Generalized error handling function */
void
F2C(exerr) (char *pname,
            char *err_string,
            int *errcode,
            int pnamelen,
            int err_stringlen)
{

  char           *proc_name, *error_string;
  if (!(proc_name = malloc((pnamelen + 1) * sizeof(char)))) {
    ex_err("exerr", "Error: failed to allocate space for process name buffer",
           EX_MEMFAIL);
    return;
  }
  if (!(error_string = malloc((err_stringlen + 1) * sizeof(char)))) {
    free(proc_name);
    ex_err("exerr", "Error: failed to allocate space for error msg buffer",
           EX_MEMFAIL);
    return;
  }
  ex_fstrncpy(proc_name, pname, pnamelen);
  ex_fstrncpy(error_string, err_string, err_stringlen);
  ex_err(proc_name, error_string, *errcode);
  free(proc_name);
  free(error_string);
}

/* Error message reporting options setting function */
void
F2C(exopts) (int *option_val,
             int *ierr)
{
  *ierr = 0;
  ex_opts((ex_options) * option_val);
  if (exerrval != 0) {
    *ierr = EX_FATAL;
  }
}

void
F2C(exmxnm) (int *idexo,
             int *length,
             int *ierr)
{
  *ierr = ex_set_max_name_length(*idexo, *length);
}

/*
 * copy EXODUS file
 */
void
F2C(excopy) (int *idexo_in,
             int *idexo_out,
             int *ierr)
{
  *ierr = ex_copy(*idexo_in, *idexo_out);
}

/*
 * get element map
 */
void

F2C(exgem) (int *idexo,
            entity_id *map_id,
            void_int *elem_map,
            int *ierr)
{
  *ierr = ex_get_num_map(*idexo, EX_ELEM_MAP, *map_id, elem_map);
}

/*
 * get partial_element map
 */
void
F2C(exgpem) (int *idexo,
             entity_id *map_id,
             void_int *start,
             void_int *count,
             void_int *elem_map,
             int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }
  
  *ierr = ex_get_partial_num_map(*idexo, EX_ELEM_MAP, *map_id, st, cnt, elem_map);
}

/*
 * get element number map
 */
void
F2C(exgenm) (int *idexo,
             void_int *elem_map,
             int *ierr)
{
  *ierr = ex_get_id_map(*idexo, EX_ELEM_MAP, elem_map);
}

/*
 * get map parameters
 */
void
F2C(exgmp) (int *idexo,
            int *num_node_maps,
            int *num_elem_maps,
            int *ierr)
{
  *ierr = ex_get_map_param(*idexo, num_node_maps, num_elem_maps);
}

/*
 * get node map
 */
void
F2C(exgnm) (int *idexo,
            entity_id *map_id,
            void_int *node_map,
            int *ierr)
{
  *ierr = ex_get_num_map(*idexo, EX_NODE_MAP, *map_id, node_map);
}

/*
 * get node number map
 */
void
F2C(exgnnm) (int *idexo,
             void_int *node_map,
             int *ierr)
{
  *ierr = ex_get_id_map(*idexo, EX_NODE_MAP, node_map);
}

/*
 * read results variables names
 */
void
F2C(exgvnm) (int *idexo,
             char *var_type,
             int *var_index,
             char *var_name,
             int *ierr,
             int var_typelen,
             int var_namelen)
{
  char           *sptr;         /* ptr to temp staging space for string */
  int             slen;
  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_MAX_READ_NAME_LENGTH); /* max string size */
  if (var_namelen < slen) {
    slen = var_namelen;
  }
  /* Allocate staging space for the variable name */
  if (!(sptr = malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  /* do ExodusII C call to read results variables names */
  if (ex_get_var_name(*idexo, var_type, *var_index, sptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up allocated space */
    return;
  }
  /* Copy Fortran variable names to staging space */
  /** printf("[exgvnm] var_name(%d): %s\n",*var_index,sptr)); **/
  memset(var_name, 0, var_namelen);
  ex_fcdcpy(var_name, slen, sptr);      /* copy string into Fortran buffer */

  free(sptr);                   /* Free up string staging area */
}

/*
 * put element map
 */
void
F2C(expem) (int *idexo,
            entity_id *map_id,
            void_int *elem_map,
            int *ierr)
{
  *ierr = ex_put_num_map(*idexo, EX_ELEM_MAP, *map_id, elem_map);
}

/*
 * put partial element map
 */
void
F2C(exppem) (int *idexo,
             entity_id *map_id,
             void_int *start,
             void_int *count,
             void_int *elem_map,
             int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idexo) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }
  *ierr = ex_put_partial_num_map(*idexo, EX_ELEM_MAP, *map_id, st, cnt, elem_map);
}

/*
 * put element number map
 */
void
F2C(expenm) (int *idexo,
             void_int *elem_map,
             int *ierr)
{
  *ierr = ex_put_id_map(*idexo, EX_ELEM_MAP, elem_map);
}

/*
 * put map parameters
 */
void
F2C(expmp) (int *idexo,
            int *num_node_maps,
            int *num_elem_maps,
            int *ierr)
{
  *ierr = ex_put_map_param(*idexo, *num_node_maps, *num_elem_maps);
}

/*
 * put node map
 */
void
F2C(expnm) (int *idexo,
            entity_id *map_id,
            void_int *node_map,
            int *ierr)
{
  *ierr = ex_put_num_map(*idexo, EX_NODE_MAP, *map_id, node_map);
}

/*
 * put node number map
 */
void
F2C(expnnm) (int *idexo,
             void_int *node_map,
             int *ierr)
{
  *ierr = ex_put_id_map(*idexo, EX_NODE_MAP, node_map);
}

/*
 * write results variable name
 */
void
F2C(expvnm) (int *idexo,
             char *var_type,
             int *var_index,
             char *var_name,
             int *ierr,
             int var_typelen,
             int var_namelen)
{
  char           *sptr;         /* ptr to temp staging space for string */
  int             slen;
  *ierr = 0;                    /* default no errror */

  slen = ex_inquire_int(*idexo, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);     /* max str size */
  if (var_namelen < slen) {
    slen = var_namelen;
  }
  /* Allocate staging space for the variable name */
  if (!(sptr = (char *) malloc((slen + 1) * sizeof(char)))) {
    *ierr = EX_MEMFAIL;
    return;
  }
  ex_fstrncpy(sptr, var_name, slen);    /* copy string into buffer */


  /* do ExodusII C call to write results variable name */
  if (ex_put_var_name(*idexo, var_type, *var_index, sptr) == EX_FATAL) {
    *ierr = EX_FATAL;
    free(sptr);                 /* free up allocated space */
    return;
  }
  free(sptr);                   /* Free up string staging area */
}

/*
 *  Get initial information from nemesis file
 */
void
F2C(exgii)(int	*idne,	
	   int	*nproc,
	   int	*nproc_in_f,
	   char	*ftype,
	   int  *ierr, 
	   size_t ftypelen)
{
  size_t slen = 1;
  char *file_type;

  /* WARNING: ftypelen SHOULD be 1, but may not be depending on how
              the Fortran programmer passed it. It is best at
              this time to hard code it per NEPII spec. */
  if (ftypelen != 1) {
#if defined(EXODUS_STRING_LENGTH_WARNING)
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,"Warning: file type string length is %d in file id %d\n",
            ftypelen, *idne);
    ex_err("negii",errmsg,EX_MSG);
#endif
    slen = ftypelen;
  }

  file_type = (char *) malloc((slen+1)*sizeof(char));

  if ((*ierr = ex_get_init_info(*idne, nproc, nproc_in_f, file_type)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to get initial information from file id %d",
	    *idne);
    ex_err("negii",errmsg,EX_MSG);
  }

  if (*ierr == 0)
    ex_fcdcpy (ftype, slen, file_type);

  free(file_type);
}

/*
 *  Write initial information from nemesis file
 */
void
F2C(expii)(int	*idne,
	   int	*nproc,
	   int	*nproc_in_f,
	   char	*ftype,
	   int  *ierr,
	   size_t ftypelen)
{

  char errmsg[MAX_ERR_LENGTH];

  size_t slen = 1;
  char *file_type;

  /* WARNING: ftypelen SHOULD be 1, but may not be depending on how
              the Fortran programmer passed it. It is best at
              this time to hard code it per NEPII spec. */
  if (ftypelen != 1) {
    slen = ftypelen;
#if defined(EXODUS_STRING_LENGTH_WARNING)
    sprintf(errmsg,"Warning: file type string length is %d in file id %d\n",
            ftypelen, *idne);
    ex_err("nepii",errmsg,EX_MSG);
#endif
  }

  file_type = (char *) malloc((slen+1)*sizeof(char));

  ex_fstrncpy (file_type, ftype, slen);

  if ((*ierr = ex_put_init_info(*idne, *nproc, *nproc_in_f, file_type)) != 0)
  {
    sprintf(errmsg,
	    "Error: failed to put initial information in file id %d",
	    *idne);
    ex_err("nepii",errmsg,EX_MSG);
  }

  free(file_type);
}

/*
 * Read initial global information
 */
void
F2C(exgig)(int	*idne,
	   void_int	*nnodes_g,
	   void_int	*nelems_g,
	   void_int	*nelem_blks_g,
	   void_int	*nnode_sets_g,
	   void_int	*nside_sets_g,
	   int	*ierr)
{
  if ((*ierr = ex_get_init_global(*idne, nnodes_g, nelems_g, nelem_blks_g,
                                  nnode_sets_g, nside_sets_g)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read initial global information from file id %d",
	    *idne);
    ex_err("negig",errmsg,EX_MSG);
  }
}

/*
 * Write initial global information
 */
void
F2C(expig)(int	*idne,
	   void_int	*nnodes_g,
	   void_int	*nelems_g,
	   void_int	*nelem_blks_g,
	   void_int	*nnode_sets_g,
	   void_int	*nside_sets_g,
	   int	*ierr)
{
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    int64_t *n_nnodes_g = (int64_t*)nnodes_g;
    int64_t *n_nelems_g = (int64_t*)nelems_g;
    int64_t *n_nelem_blks_g = (int64_t*)nelem_blks_g;
    int64_t *n_nnode_sets_g = (int64_t*)nnode_sets_g;
    int64_t *n_nside_sets_g = (int64_t*)nside_sets_g;
    *ierr =  ex_put_init_global(*idne, *n_nnodes_g, *n_nelems_g, *n_nelem_blks_g,
				*n_nnode_sets_g, *n_nside_sets_g);
  } else {
    int *n_nnodes_g = (int*)nnodes_g;
    int *n_nelems_g = (int*)nelems_g;
    int *n_nelem_blks_g = (int*)nelem_blks_g;
    int *n_nnode_sets_g = (int*)nnode_sets_g;
    int *n_nside_sets_g = (int*)nside_sets_g;
    *ierr =  ex_put_init_global(*idne, *n_nnodes_g, *n_nelems_g, *n_nelem_blks_g,
				*n_nnode_sets_g, *n_nside_sets_g);
  }

  if (*ierr != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store initial global information in file id %d",
	    *idne);
    ex_err("nepig",errmsg,EX_MSG);
  }
}

/*
 * Read load balance parameters
 */
void
F2C(exglbp)(int	*idne,
	    void_int	*nint_nodes,
	    void_int	*nbor_nodes,
	    void_int	*next_nodes,
	    void_int	*nint_elems,
	    void_int	*nbor_elems,
	    void_int	*nnode_cmaps,
	    void_int	*nelem_cmaps,
	    int	*processor,
	    int	*ierr)
{
  if ((*ierr = ex_get_loadbal_param(*idne, nint_nodes, nbor_nodes,
                                    next_nodes, nint_elems, nbor_elems,
                                    nnode_cmaps, nelem_cmaps, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read load balance parameters from file id %d",
	    *idne);
    ex_err("neglbp",errmsg,EX_MSG);
  }
}

/*
 * Write load balance parameters
 */
void
F2C(explbp)(int	*idne,
	    void_int	*nint_nodes,
	    void_int	*nbor_nodes,
	    void_int	*next_nodes,
	    void_int	*nint_elems,
	    void_int	*nbor_elems,
	    void_int	*nnode_cmaps,
	    void_int	*nelem_cmaps,
	    int	*processor,
	    int	*ierr)	
{
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    int64_t *n_nint_nodes = (int64_t*)nint_nodes;
    int64_t *n_nbor_nodes = (int64_t*)nbor_nodes;
    int64_t *n_next_nodes = (int64_t*)next_nodes;
    int64_t *n_nint_elems = (int64_t*)nint_elems;
    int64_t *n_nbor_elems = (int64_t*)nbor_elems;
    int64_t *n_nnode_cmaps = (int64_t*)nnode_cmaps;
    int64_t *n_nelem_cmaps = (int64_t*)nelem_cmaps;
    *ierr = ex_put_loadbal_param(*idne, *n_nint_nodes, *n_nbor_nodes,
				 *n_next_nodes, *n_nint_elems, *n_nbor_elems,
				 *n_nnode_cmaps, *n_nelem_cmaps,
				 *processor);
  } else {
    int *n_nint_nodes = (int*)nint_nodes;
    int *n_nbor_nodes = (int*)nbor_nodes;
    int *n_next_nodes = (int*)next_nodes;
    int *n_nint_elems = (int*)nint_elems;
    int *n_nbor_elems = (int*)nbor_elems;
    int *n_nnode_cmaps = (int*)nnode_cmaps;
    int *n_nelem_cmaps = (int*)nelem_cmaps;
    *ierr = ex_put_loadbal_param(*idne, *n_nint_nodes, *n_nbor_nodes,
				 *n_next_nodes, *n_nint_elems, *n_nbor_elems,
				 *n_nnode_cmaps, *n_nelem_cmaps,
				 *processor);
  }
  if (*ierr != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store load balance parameters in file id %d",
	    *idne);
    ex_err("neplbp",errmsg,EX_MSG);
  }
}

/*
 * Write concatenated load balance parameters
 */
void
F2C(explbpc)(int *idne,
	     void_int *nint_nodes,	
	     void_int *nbor_nodes,	
	     void_int *next_nodes,	
	     void_int *nint_elems,	
	     void_int *nbor_elems,	
	     void_int *nnode_cmaps,	
	     void_int *nelem_cmaps,	
	     int *ierr)	
{
  if ((*ierr = ex_put_loadbal_param_cc(*idne, nint_nodes, nbor_nodes,
                                       next_nodes, nint_elems, nbor_elems,
                                       nnode_cmaps, nelem_cmaps)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store load balance parameters in file id %d",
	    *idne);
    ex_err("neplbpc",errmsg,EX_MSG);
  }
}

/*
 * Read global node set parameters
 */
void
F2C(exgnspg)(int *idne,
	     void_int *ns_ids_glob,
	     void_int *ns_n_cnt_glob,
	     void_int *ns_df_cnt_glob,
	     int *ierr)
{
  if ((*ierr = ex_get_ns_param_global(*idne, ns_ids_glob, ns_n_cnt_glob, ns_df_cnt_glob)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read global node set parameters from file id %d",
	    *idne);
    ex_err("negnspg",errmsg,EX_MSG);
  }
}

/*
 * Write global node set parameters
 */
void
F2C(expnspg)(int *idne,
	     void_int *global_ids,
	     void_int *global_n_cnts,
	     void_int *global_df_cnts,
	     int *ierr)
{
  if ((*ierr = ex_put_ns_param_global(*idne, global_ids, global_n_cnts, global_df_cnts)) != 0)
  {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store global node set parameters in file id %d",
	    *idne);
    ex_err("nepnspg",errmsg,EX_MSG);
  }
}

/*
 * Read global side set parameters
 */
void
F2C(exgsspg)(int *idne,
	     void_int *ss_ids_glob,
	     void_int *ss_n_cnt_glob,
	     void_int *ss_df_cnt_glob,
	     int *ierr)
{

  if ((*ierr = ex_get_ss_param_global(*idne, ss_ids_glob, ss_n_cnt_glob, ss_df_cnt_glob)) != 0)
  {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read global side set parameters from file id %d",
	    *idne);
    ex_err("negsspg",errmsg,EX_MSG);
  }
}

/*
 * Write global side set parameters
 */
void
F2C(expsspg)(int *idne,
	     void_int *global_ids,
	     void_int *global_el_cnts,
	     void_int *global_df_cnts,
	     int *ierr)
{
  if ((*ierr = ex_put_ss_param_global(*idne, global_ids, global_el_cnts, global_df_cnts)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store global side set parameters in file id %d",
	    *idne);
    ex_err("nepsspg",errmsg,EX_MSG);
  }
}

/*
 * Read global element block information
 */
void
F2C(exgebig)(int *idne,
	     void_int *el_blk_ids,
	     void_int *el_blk_cnts,
	     int *ierr)
{
  if ((*ierr = ex_get_eb_info_global(*idne, el_blk_ids, el_blk_cnts)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read global element block info from file id %d",
	    *idne);
    ex_err("negebig",errmsg,EX_MSG);
  }
}

/*
 * Write global element block information
 */
void
F2C(expebig)(int *idne,
	     void_int *el_blk_ids,
	     void_int *el_blk_cnts,
	     int *ierr)
{
  if ((*ierr = ex_put_eb_info_global(*idne, el_blk_ids, el_blk_cnts)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to store global element block info in file id %d",
	    *idne);
    ex_err("nepebig",errmsg,EX_MSG);
  }
}

/*
 * Read side set element list and side set side list
 */
void
F2C(exgnss)(int *idne,
	    entity_id *ss_id,
	    void_int *start,
	    void_int *count,
	    void_int *ss_elem_list,
	    void_int *ss_side_list,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_side_set(*idne, *ss_id, st, cnt, ss_elem_list, ss_side_list)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read side set element list from file id %d",
	    *idne);
    ex_err("negnss",errmsg,EX_MSG);
  }
}

/*
 * Write side set element list and side set side list
 */
void
F2C(expnss)(int *idne,
	    entity_id *ss_id,
	    void_int *start,
	    void_int *count,
	    void_int *ss_elem_list,
	    void_int *ss_side_list,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_side_set(*idne, *ss_id, st, cnt, ss_elem_list, ss_side_list)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write side set element list to file id %d",
	    *idne);
    ex_err("nepnss",errmsg,EX_MSG);
  }
}

/*
 * Read side set distribution factor
 */
void
F2C(exgnssd)(int *idne,
	     entity_id *ss_id,
	     void_int *start,
	     void_int *count,
	     real *ss_df,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_side_set_df(*idne, *ss_id, st, cnt, ss_df)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read side set dist factor from file id %d",
	    *idne);
    ex_err("negnssd",errmsg,EX_MSG);
  }
}

/*
 * Write side set distribution factor
 */
void
F2C(expnssd)(int *idne,
	     entity_id *ss_id,
	     void_int *start,
	     void_int *count,
	     real *ss_df,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_side_set_df(*idne, *ss_id, st, cnt, ss_df)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write side set dist factor to file id %d",
	    *idne);
    ex_err("nepnssd",errmsg,EX_MSG);
  }
}

/*
 * Read node set list for a single node set
 */
void
F2C(exgnns)(int *idne,
	    entity_id *ns_id,
	    void_int *start,
	    void_int *count,
	    void_int *ns_node_list,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_node_set(*idne, *ns_id, st, cnt,ns_node_list)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read node set node list from file id %d",
	    *idne);
    ex_err("negnns",errmsg,EX_MSG);
  }
}

/*
 * Write node set list for a single node set
 */
void
F2C(expnns)(int *idne,
	    entity_id *ns_id,
	    void_int *start,
	    void_int *count,
	    void_int *ns_node_list,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_node_set(*idne, *ns_id, st, cnt, ns_node_list)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write node set node list to file id %d",
	    *idne);
    ex_err("nepnns",errmsg,EX_MSG);
  }
}

/*
 * Read node set distribution factor
 */
void
F2C(exgnnsd)(int *idne,
	     entity_id *ns_id,
	     void_int *start,
	     void_int *count,
	     real *ns_df,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_node_set_df(*idne, *ns_id, st, cnt, ns_df)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read node set dist factor from file id %d",
	    *idne);
    ex_err("negnnsd",errmsg,EX_MSG);
  }
}

/*
 * Write node set distribution factor
 */
void
F2C(expnnsd)(int *idne,
	     entity_id *ns_id,
	     void_int *start,
	     void_int *count,
	     real *ns_df,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_node_set_df(*idne, *ns_id, st, cnt, ns_df)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write node set dist factor to file id %d",
	    *idne);
    ex_err("nepnnsd",errmsg,EX_MSG);
  }
}

/*
 * Read coordinates of the nodes
 */
void
F2C(exgncor)(int *idne,
	     void_int *start,
	     void_int *count,
	     real *x_coor,
	     real *y_coor,
	     real *z_coor,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_coord(*idne, st, cnt, x_coor, y_coor, z_coor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read node coordinates from file id %d",
	    *idne);
    ex_err("negcor",errmsg,EX_MSG);
  }
}

/*
 * Write coordinates of the nodes
 */
void
F2C(expncor)(int *idne,
	     void_int *start,
	     void_int *count,
	     real *x_coor,
	     real *y_coor,
	     real *z_coor,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_coord(*idne, st, cnt, x_coor, y_coor, z_coor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write node coordinates to file id %d",
	    *idne);
    ex_err("nepcor",errmsg,EX_MSG);
  }
}

/*
 * Read an element block's connectivity list
 */
void
F2C(exgnec)(int *idne,
	    entity_id *elem_blk_id,
	    void_int *start,
	    void_int *count,
	    void_int *connect,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_elem_conn(*idne, *elem_blk_id, st, cnt, connect)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read element block connectivity from file id %d",
	    *idne);
    ex_err("negnec",errmsg,EX_MSG);
  }
}

/*
 * Write an element block's connectivity list
 */
void
F2C(expnec)(int *idne,
	    entity_id *elem_blk_id,
	    void_int *start,
	    void_int *count,
	    void_int *connect,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_elem_conn(*idne, *elem_blk_id, st, cnt, connect)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write element block connectivity to file id %d",
	    *idne);
    ex_err("negnec",errmsg,EX_MSG);
  }
}

/*
 * Read an element block's attributes
 */
void
F2C(exgneat)(int *idne,
	     entity_id *elem_blk_id,
	     void_int *start,
	     void_int *count,
	     real *attrib,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_elem_attr(*idne, *elem_blk_id, st, cnt, attrib)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read element block attribute from file id %d",
	    *idne);
    ex_err("negneat",errmsg,EX_MSG);
  }
}

/*
 * Write an element block's attributes
 */
void
F2C(expneat)(int *idne,
	     entity_id *elem_blk_id,
	     void_int *start,
	     void_int *count,
	     real *attrib,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_n_elem_attr(*idne, *elem_blk_id, st, cnt, attrib)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write element block attribute to file id %d",
	    *idne);
    ex_err("nepneat",errmsg,EX_MSG);
  }
}

/*
 * Read the element type for a specific element block
 */
void
F2C(exgelt)(int *idne,
	    entity_id *elem_blk_id,
	    char *elem_type,
	    int *ierr,
	    size_t elem_typelen)
{
  size_t slen = MAX_STR_LENGTH;
  char *etype;

  /* WARNING: ftypelen SHOULD be MAX_STR_LENGTH, but may not be depending
              on how the Fortran programmer passed it. It is best at
              this time to hard code it per NEMESIS spec. */
  if (elem_typelen != MAX_STR_LENGTH) {
#if defined(EXODUS_STRING_LENGTH_WARNING)
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,"Warning: element type string length is %d in file id %d\n",
            elem_typelen, *idne);
    ex_err("negelt",errmsg,EX_MSG);
#endif
    slen = elem_typelen;
  }

  etype = (char *) malloc((slen+1)*sizeof(char));

  if ((*ierr = ex_get_elem_type(*idne, *elem_blk_id, etype)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read element block type from file id %d",
	    *idne);
    ex_err("negelt",errmsg,EX_MSG);
  }

  if (*ierr == 0)
    ex_fcdcpy (elem_type, slen, etype);

  free(etype);
}

/*
 * Read a variable for an element block
 */
void
F2C(exgnev)(int *idne,
	    int *time_step,
	    int *elem_var_index,
	    entity_id *elem_blk_id,
	    void_int *num_elem_this_blk,
	    void_int *start,
	    void_int *count,
	    real *elem_var_vals,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_var(*idne, *time_step, EX_ELEM_BLOCK, *elem_var_index,
			    *elem_blk_id, st, cnt, elem_var_vals)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read element block variable from file id %d",
	    *idne);
    ex_err("negnec",errmsg,EX_MSG);
  }
}

/*
 * Write a variable slab for an element block
 */
void
F2C(expevs)(int *idne,
	    int *time_step,
	    int *elem_var_index,
	    entity_id *elem_blk_id,
	    void_int *start,
	    void_int *count,
	    real *elem_var_vals,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_elem_var_slab(*idne, *time_step, *elem_var_index,
                                    *elem_blk_id, st, cnt, elem_var_vals)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write elem block variable slab to file id %d",
	    *idne);
    ex_err("negnec",errmsg,EX_MSG);
  }
}

/*
 * Read the values of a single nodal variable for a single time step
 */
void
F2C(exgnnv)(int *idne,
	    int *time_step,
	    int *nodal_var_index,
	    void_int *start,
	    void_int *count,
	    real *nodal_vars,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_get_n_var(*idne, *time_step, EX_NODAL, *nodal_var_index,
			    1, st, cnt, nodal_vars)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read nodal variable from file id %d",
	    *idne);
    ex_err("negnnv",errmsg,EX_MSG);
  }
}

/*
 * Write nodal variable slab
 */
void
F2C(expnvs)(int *idne,
	    int *time_step,
	    int *nodal_var_index,
	    void_int *start,
	    void_int *count,
	    real *nodal_var_vals,
	    int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
  }

  if ((*ierr = ex_put_nodal_var_slab(*idne, *time_step, *nodal_var_index,
                                     st, cnt, nodal_var_vals)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write nodal variable slab to file id %d",
	    *idne);
    ex_err("nepnvs",errmsg,EX_MSG);
  }
}

/*
 * Read the element numbering map
 */
void
F2C(exgnenm)(int *idne,
	     void_int *starte,
	     void_int *num_ent,
	     void_int *elem_map,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)starte;
    cnt = *(int64_t*)num_ent;
  } else {
    st = *(int*)starte;
    cnt = *(int*)num_ent;
  }

  if ((*ierr = ex_get_n_elem_num_map(*idne, st, cnt, elem_map)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read element numbering map from file id %d",
	    *idne);
    ex_err("negnenm",errmsg,EX_MSG);
  }
}

/*
 * Write the element numbering map
 */
void
F2C(expnenm)(int *idne,
	     void_int *starte,
	     void_int *num_ent,
	     void_int *elem_map,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)starte;
    cnt = *(int64_t*)num_ent;
  } else {
    st = *(int*)starte;
    cnt = *(int*)num_ent;
  }

  if ((*ierr = ex_put_partial_id_map(*idne, EX_ELEM_MAP, st, cnt, elem_map)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write element numbering map to file id %d",
	    *idne);
    ex_err("nepnenm",errmsg,EX_MSG);
  }
}

/*
 * Read the node numbering map
 */
void
F2C(exgnnnm)(int *idne,
	     void_int *startn,
	     void_int *num_ent,
	     void_int *node_map,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)startn;
    cnt = *(int64_t*)num_ent;
  } else {
    st = *(int*)startn;
    cnt = *(int*)num_ent;
  }

  if ((*ierr = ex_get_n_node_num_map(*idne, st, cnt, node_map)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read node numbering map from file id %d",
	    *idne);
    ex_err("negnnnm",errmsg,EX_MSG);
  }
}

/*
 * Write the node numbering map
 */
void
F2C(expnnnm)(int *idne,
	     void_int *startn,
	     void_int *num_ent,
	     void_int *node_map,
	     int *ierr)
{
  int64_t st, cnt;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)startn;
    cnt = *(int64_t*)num_ent;
  } else {
    st = *(int*)startn;
    cnt = *(int*)num_ent;
  }

  if ((*ierr = ex_put_partial_id_map(*idne, EX_NODE_MAP, st, cnt, node_map)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write node numbering map to file id %d",
	    *idne);
    ex_err("nepnnnm",errmsg,EX_MSG);
  }
}

/*
 * Read the node map for a processor
 */
void
F2C(exgnmp)(int *idne,
	   void_int *node_mapi,
	   void_int *node_mapb,
	   void_int *node_mape,
	   int *processor,
	   int *ierr)
{
  if ((*ierr = ex_get_processor_node_maps(*idne, node_mapi, node_mapb, node_mape, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read processor node map from file id %d",
	    *idne);
    ex_err("negnm",errmsg,EX_MSG);
  }
}

/*
 * Write a node map for a processor
 */
void
F2C(expnmp)(int *idne,
	   void_int *node_mapi,
	   void_int *node_mapb,
	   void_int *node_mape,
	   int *processor,
	   int *ierr)
{
  if ((*ierr = ex_put_processor_node_maps(*idne, node_mapi, node_mapb, node_mape, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write processor node map to file id %d",
	    *idne);
    ex_err("nepnm",errmsg,EX_MSG);
  }
}

/*
 * Read the element map for a processor
 */
void
F2C(exgemp)(int *idne,
	   void_int *elem_mapi,
	   void_int *elem_mapb,
	   int *processor,
	   int *ierr)
{
  if ((*ierr = ex_get_processor_elem_maps(*idne, elem_mapi, elem_mapb, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read processor element map from file id %d",
	    *idne);
    ex_err("negem",errmsg,EX_MSG);
  }
}

/*
 * Write the element map for a processor
 */
void
F2C(expemp)(int *idne,
	   void_int *elem_mapi,
	   void_int *elem_mapb,
	   int *processor,
	   int *ierr)
{
  if ((*ierr = ex_put_processor_elem_maps(*idne, elem_mapi, elem_mapb, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write processor element map to file id %d",
	    *idne);
    ex_err("nepem",errmsg,EX_MSG);
  }
}

/*
 * Read the communications map parameters for a single processor
 */
void
F2C(exgcmp)(int *idne,
	    void_int *ncmap_ids,
	    void_int *ncmap_node_cnts,
	    void_int *ecmap_ids,
	    void_int *ecmap_elem_cnts,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_get_cmap_params(*idne, ncmap_ids, ncmap_node_cnts,
                                  ecmap_ids, ecmap_elem_cnts, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read comm map parameters from file id %d",
	    *idne);
    ex_err("negcmp",errmsg,EX_MSG);
  }
}

/*
 * Write the communications map parameters for a single processor
 */
void
F2C(expcmp)(int *idne,
	    void_int *nmap_ids,
	    void_int *nmap_node_cnts,
	    void_int *emap_ids,
	    void_int *emap_elem_cnts,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_put_cmap_params(*idne, nmap_ids, nmap_node_cnts,
                                  emap_ids, emap_elem_cnts, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write comm map parameters to file id %d",
	    *idne);
    ex_err("nepcmp",errmsg,EX_MSG);
  }
}

/*
 * Write the communications map parameters for all processors
 */
void
F2C(expcmpc)(int *idne,
	     void_int *nmap_ids,
	     void_int *nmap_node_cnts,
	     void_int *nproc_ptrs,
	     void_int *emap_ids,
	     void_int *emap_elem_cnts,
	     void_int *eproc_ptrs,
	     int *ierr)
{
  if ((*ierr = ex_put_cmap_params_cc(*idne, nmap_ids, nmap_node_cnts,
                                     nproc_ptrs, emap_ids, emap_elem_cnts,
                                     eproc_ptrs)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write comm map parameters to file id %d",
	    *idne);
    ex_err("nepcmpc",errmsg,EX_MSG);
  }
}

/*
 * Read the nodal communications map for a single processor
 */
void
F2C(exgncm)(int *idne,
	    entity_id *map_id,
	    void_int *node_ids,
	    void_int *proc_ids,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_get_node_cmap(*idne, *map_id, node_ids, proc_ids, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read nodal communications map from file id %d",
	    *idne);
    ex_err("negncm",errmsg,EX_MSG);
  }
}

/*
 * Write the nodal communications map for a single processor
 */
void
F2C(expncm)(int *idne,
	    entity_id *map_id,
	    void_int *node_ids,
	    void_int *proc_ids,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_put_node_cmap(*idne, *map_id, node_ids, proc_ids, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write nodal communications map to file id %d",
	    *idne);
    ex_err("nepncm",errmsg,EX_MSG);
  }
}

/*
 * Read the elemental communications map for a single processor
 */
void
F2C(exgecm)(int *idne,
	    entity_id *map_id,
	    void_int *elem_ids,
	    void_int *side_ids,
	    void_int *proc_ids,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_get_elem_cmap(*idne, *map_id, elem_ids, side_ids, proc_ids, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to read elemental comm map from file id %d",
	    *idne);
    ex_err("negecm",errmsg,EX_MSG);
  }
}

/*
 * Write the elemental communications map for a single processor
 */
void
F2C(expecm)(int *idne,
	    entity_id *map_id,
	    void_int *elem_ids,
	    void_int *side_ids,
	    void_int *proc_ids,
	    int *processor,
	    int *ierr)
{
  if ((*ierr = ex_put_elem_cmap(*idne, *map_id, elem_ids, side_ids, proc_ids, *processor)) != 0) {
    char errmsg[MAX_ERR_LENGTH];
    sprintf(errmsg,
	    "Error: failed to write elemental comm map to file id %d",
	    *idne);
    ex_err("nepecm",errmsg,EX_MSG);
  }
}
