/*
 * Copyright (c) 1998 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.
 * 
 */
/*====================================================================
 * ------------------------
 * | CVS File Information |
 * ------------------------
 *
 * $RCSfile: ne_jack.src,v $
 *
 * $Author: gdsjaar $
 *
 * $Date: 2007/10/31 21:39:17 $
 *
 * $Revision: 1.14 $
 *
 *====================================================================*/
/*
 * OVERVIEW
 *
 * This file contains jacket routines written in C for interfacing Fortran
 * NemesisI function calls to the actual C binding for NemsisI.  This code
 * is written explicitly for DARWIN.  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 */
typedef double real;
typedef ex_entity_id entity_id;
#ifdef ADDC_
#define F2C(name) name##4_
#else
#define F2C(name) name##4
#endif

#else
/* 32-bit */
typedef float real;
typedef int entity_id;
#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 int that contains a Exodus-specific error code */

/* blank fill C string to make FORTRAN string */
static void
ex_fcdcpy (char *fstring, size_t fslen, char *sstring)
                                /* output string to be blank-filled */
                                /* length of output string */
                                /* input string, null-terminated */
{
  size_t i, len = strlen(sstring);
  
  for (i = 0; i < len; i++)
    *(fstring + i) = *(sstring + i);
  for (i = len; i < fslen; i++)
    *(fstring + i) = ' ';
}

/* copy function used to copy strings and strip trailing blanks */
static void
ex_fstrncpy (char *target, char *source, size_t maxlen)
                                /* space to be copied into */
                                /* string to be copied */
                                /* maximum length of *source */
{
    while (maxlen-- && *source != '\0')
        *target++ = *source++;
    while (*(--target) == ' '); /* strip blanks */
    *(++target) = '\0';         /* insert new EOS marker */
}

/* Above are utility functions used below                                   */
/* ======================================================================== */
/* Below are the nemesis 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...
 */

/*
 *  Get initial information from nemesis file
 */
void
F2C(negii)(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(nepii)(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(negig)(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(nepig)(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(neglbp)(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(neplbp)(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(neplbpc)(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(negnspg)(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(nepnspg)(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(negsspg)(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(nepsspg)(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(negebig)(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(nepebig)(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(negnss)(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(nepnss)(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(negnssd)(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(nepnssd)(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(negnns)(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(nepnns)(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(negnnsd)(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(nepnnsd)(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(negcor)(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(nepcor)(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(negnec)(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(nepnec)(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(negneat)(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(nepneat)(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(negelt)(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(negnev)(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, ne;
  if (ex_int64_status(*idne) & EX_BULK_INT64_API) {
    st = *(int64_t*)start;
    cnt = *(int64_t*)count;
    ne = *(int64_t*)num_elem_this_blk;
  } else {
    st = *(int*)start;
    cnt = *(int*)count;
    ne = *(int*)num_elem_this_blk;
  }

  if ((*ierr = ex_get_n_elem_var(*idne, *time_step, *elem_var_index,
				 *elem_blk_id, ne, 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(nepevs)(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(negnnv)(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_nodal_var(*idne, *time_step, *nodal_var_index,
                                  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(nepnvs)(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(negnenm)(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(nepnenm)(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_n_elem_num_map(*idne, 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(negnnnm)(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(nepnnnm)(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_n_node_num_map(*idne, 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(negnm)(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(nepnm)(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(negem)(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(nepem)(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(negcmp)(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(nepcmp)(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(nepcmpc)(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(negncm)(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(nepncm)(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(negecm)(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(nepecm)(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);
  }
}

